package security

import (
	"fmt"
	"os/exec"
	"runtime"
	"strings"
)

// KillSwitch управляет блокировкой интернета при разрыве VPN
type KillSwitch struct {
	enabled       bool
	originalRules []string
}

// NewKillSwitch создает новый Kill Switch
func NewKillSwitch() *KillSwitch {
	return &KillSwitch{
		enabled:       false,
		originalRules: []string{},
	}
}

// Enable включает Kill Switch (блокирует весь трафик кроме VPN)
func (ks *KillSwitch) Enable(vpnInterface string, allowedIPs []string) error {
	if runtime.GOOS != "windows" {
		return ks.enableUnix(vpnInterface, allowedIPs)
	}
	return ks.enableWindows(vpnInterface, allowedIPs)
}

// Disable отключает Kill Switch (восстанавливает нормальный трафик)
func (ks *KillSwitch) Disable() error {
	if runtime.GOOS != "windows" {
		return ks.disableUnix()
	}
	return ks.disableWindows()
}

// enableWindows включает Kill Switch на Windows через Windows Firewall
func (ks *KillSwitch) enableWindows(vpnInterface string, allowedIPs []string) error {
	// Создаем правило блокировки всего исходящего трафика
	cmd := exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
		"name=VPN_KillSwitch_Block_Out",
		"dir=out",
		"action=block",
		"enable=yes")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка создания правила блокировки: %w", err)
	}

	// Создаем правило блокировки всего входящего трафика
	cmd = exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
		"name=VPN_KillSwitch_Block_In",
		"dir=in",
		"action=block",
		"enable=yes")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка создания правила блокировки: %w", err)
	}

	// Разрешаем локальный трафик (127.0.0.1)
	cmd = exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
		"name=VPN_KillSwitch_Allow_Localhost",
		"dir=out",
		"action=allow",
		"remoteip=127.0.0.1",
		"enable=yes")
	
	cmd.Run() // Игнорируем ошибку

	// Разрешаем трафик к VPN серверам
	for _, ip := range allowedIPs {
		cmd = exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
			fmt.Sprintf("name=VPN_KillSwitch_Allow_%s", strings.ReplaceAll(ip, ".", "_")),
			"dir=out",
			"action=allow",
			fmt.Sprintf("remoteip=%s", ip),
			"enable=yes")
		
		cmd.Run() // Игнорируем ошибки для отдельных IP
	}

	ks.enabled = true
	return nil
}

// disableWindows отключает Kill Switch на Windows
func (ks *KillSwitch) disableWindows() error {
	if !ks.enabled {
		return nil
	}

	// Удаляем все правила Kill Switch
	rules := []string{
		"VPN_KillSwitch_Block_Out",
		"VPN_KillSwitch_Block_In",
		"VPN_KillSwitch_Allow_Localhost",
	}

	for _, rule := range rules {
		cmd := exec.Command("netsh", "advfirewall", "firewall", "delete", "rule",
			fmt.Sprintf("name=%s", rule))
		cmd.Run() // Игнорируем ошибки
	}

	// Удаляем правила для разрешенных IP (пытаемся удалить все возможные)
	// Получаем список всех правил с префиксом VPN_KillSwitch_Allow_
	listCmd := exec.Command("netsh", "advfirewall", "firewall", "show", "rule", "name=all")
	output, _ := listCmd.Output()
	
	lines := strings.Split(string(output), "\n")
	for _, line := range lines {
		if strings.Contains(line, "VPN_KillSwitch_Allow_") {
			parts := strings.Split(line, ":")
			if len(parts) >= 2 {
				ruleName := strings.TrimSpace(parts[1])
				deleteCmd := exec.Command("netsh", "advfirewall", "firewall", "delete", "rule",
					fmt.Sprintf("name=%s", ruleName))
				deleteCmd.Run()
			}
		}
	}

	ks.enabled = false
	return nil
}

// enableUnix включает Kill Switch на Unix системах через iptables
func (ks *KillSwitch) enableUnix(vpnInterface string, allowedIPs []string) error {
	// Сохраняем текущие правила
	cmd := exec.Command("iptables-save")
	output, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("ошибка сохранения правил iptables: %w", err)
	}
	ks.originalRules = strings.Split(string(output), "\n")

	// Блокируем весь исходящий трафик по умолчанию
	cmd = exec.Command("iptables", "-P", "OUTPUT", "DROP")
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка установки политики OUTPUT: %w", err)
	}

	// Разрешаем локальный трафик
	cmd = exec.Command("iptables", "-A", "OUTPUT", "-o", "lo", "-j", "ACCEPT")
	cmd.Run()

	// Разрешаем трафик через VPN интерфейс
	if vpnInterface != "" {
		cmd = exec.Command("iptables", "-A", "OUTPUT", "-o", vpnInterface, "-j", "ACCEPT")
		cmd.Run()
	}

	// Разрешаем трафик к VPN серверам
	for _, ip := range allowedIPs {
		cmd = exec.Command("iptables", "-A", "OUTPUT", "-d", ip, "-j", "ACCEPT")
		cmd.Run()
	}

	ks.enabled = true
	return nil
}

// disableUnix отключает Kill Switch на Unix системах
func (ks *KillSwitch) disableUnix() error {
	if !ks.enabled {
		return nil
	}

	// Восстанавливаем политику по умолчанию
	cmd := exec.Command("iptables", "-P", "OUTPUT", "ACCEPT")
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка восстановления политики: %w", err)
	}

	// Очищаем цепочку OUTPUT
	cmd = exec.Command("iptables", "-F", "OUTPUT")
	cmd.Run()

	ks.enabled = false
	return nil
}

// IsEnabled проверяет, включен ли Kill Switch
func (ks *KillSwitch) IsEnabled() bool {
	return ks.enabled
}
