package proxy

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

var (
	wininet                      = syscall.NewLazyDLL("wininet.dll")
	internetSetOptionW           = wininet.NewProc("InternetSetOptionW")
	INTERNET_OPTION_SETTINGS_CHANGED = 39
	INTERNET_OPTION_REFRESH          = 37
)

// EnableSystemProxy включает системный прокси в Windows для ВСЕХ приложений
func EnableSystemProxy(proxyAddr string) error {
	// Включаем прокси через реестр
	cmd := exec.Command("reg", "add",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyEnable",
		"/t", "REG_DWORD",
		"/d", "1",
		"/f")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка включения прокси: %w", err)
	}

	// Устанавливаем адрес прокси (используем socks= для SOCKS5)
	cmd = exec.Command("reg", "add",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyServer",
		"/t", "REG_SZ",
		"/d", fmt.Sprintf("socks=%s", proxyAddr),
		"/f")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка установки адреса прокси: %w", err)
	}

	// Отключаем прокси для локальных адресов
	cmd = exec.Command("reg", "add",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyOverride",
		"/t", "REG_SZ",
		"/d", "<local>;localhost;127.*;10.*;172.16.*;172.31.*;192.168.*",
		"/f")
	
	cmd.Run() // Игнорируем ошибку

	// Применяем изменения немедленно через WinINet API
	notifySystemProxyChange()

	// Обновляем настройки Internet Explorer
	refreshIESettings()

	// Уведомляем систему о изменении настроек сети
	notifyNetworkChange()

	return nil
}

// DisableSystemProxy отключает системный прокси в Windows
func DisableSystemProxy() error {
	// Отключаем прокси
	cmd := exec.Command("reg", "add",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyEnable",
		"/t", "REG_DWORD",
		"/d", "0",
		"/f")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка отключения прокси: %w", err)
	}

	// Очищаем адрес прокси
	cmd = exec.Command("reg", "delete",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyServer",
		"/f")
	
	cmd.Run() // Игнорируем ошибку, если ключ не существует

	// Обновляем настройки
	refreshIESettings()

	return nil
}

// GetSystemProxyStatus проверяет статус системного прокси
func GetSystemProxyStatus() (bool, string, error) {
	// Проверяем, включен ли прокси
	cmd := exec.Command("reg", "query",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyEnable")
	
	output, err := cmd.Output()
	if err != nil {
		return false, "", nil
	}

	enabled := strings.Contains(string(output), "0x1")

	// Получаем адрес прокси
	cmd = exec.Command("reg", "query",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyServer")
	
	output, err = cmd.Output()
	proxyAddr := ""
	if err == nil {
		lines := strings.Split(string(output), "\n")
		for _, line := range lines {
			if strings.Contains(line, "ProxyServer") {
				parts := strings.Fields(line)
				if len(parts) >= 3 {
					proxyAddr = parts[len(parts)-1]
				}
			}
		}
	}

	return enabled, proxyAddr, nil
}

func refreshIESettings() {
	// Используем rundll32 для обновления настроек Internet Explorer
	cmd := exec.Command("rundll32.exe", "inetcpl.cpl,ClearMyTracksByProcess", "8")
	cmd.Run()
}

// notifySystemProxyChange уведомляет систему об изменении прокси через WinINet API
func notifySystemProxyChange() {
	// Уведомляем об изменении настроек
	internetSetOptionW.Call(
		0,
		uintptr(INTERNET_OPTION_SETTINGS_CHANGED),
		0,
		0,
	)
	
	// Обновляем настройки
	internetSetOptionW.Call(
		0,
		uintptr(INTERNET_OPTION_REFRESH),
		0,
		0,
	)
}

// notifyNetworkChange уведомляет систему об изменении сетевых настроек
func notifyNetworkChange() {
	// Используем netsh для сброса кэша DNS и обновления настроек
	exec.Command("ipconfig", "/flushdns").Run()
	
	// Перезапускаем сетевые службы для применения изменений
	exec.Command("net", "stop", "WinHttpAutoProxySvc").Run()
	exec.Command("net", "start", "WinHttpAutoProxySvc").Run()
}

// EnableSystemProxyHTTP включает HTTP прокси (для совместимости с некоторыми приложениями)
func EnableSystemProxyHTTP(httpProxyAddr string) error {
	// Устанавливаем HTTP прокси
	cmd := exec.Command("reg", "add",
		"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyServer",
		"/t", "REG_SZ",
		"/d", fmt.Sprintf("http=%s;https=%s", httpProxyAddr, httpProxyAddr),
		"/f")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка установки HTTP прокси: %w", err)
	}

	notifySystemProxyChange()
	return nil
}

// SetProxyForAllUsers устанавливает прокси для всех пользователей (требует прав администратора)
func SetProxyForAllUsers(proxyAddr string) error {
	// Устанавливаем в HKLM для всех пользователей
	cmd := exec.Command("reg", "add",
		"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyEnable",
		"/t", "REG_DWORD",
		"/d", "1",
		"/f")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("требуются права администратора: %w", err)
	}

	cmd = exec.Command("reg", "add",
		"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
		"/v", "ProxyServer",
		"/t", "REG_SZ",
		"/d", fmt.Sprintf("socks=%s", proxyAddr),
		"/f")
	
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("ошибка установки прокси для всех пользователей: %w", err)
	}

	notifySystemProxyChange()
	return nil
}
