package system

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

	"github.com/sirupsen/logrus"
)

type SystemProxy struct {
	logger       *logrus.Logger
	proxyAddr    string
	backupConfig map[string]string
}

type Config struct {
	HTTPProxy  string
	HTTPSProxy string
	SOCKSProxy string
	NoProxy    []string
}

func NewSystemProxy(proxyAddr string, logger *logrus.Logger) *SystemProxy {
	return &SystemProxy{
		logger:       logger,
		proxyAddr:    proxyAddr,
		backupConfig: make(map[string]string),
	}
}

// SetSystemProxy 设置系统代理
func (sp *SystemProxy) SetSystemProxy(config Config) error {
	sp.logger.Info("Setting system proxy configuration")

	// 备份当前配置
	if err := sp.backupCurrentConfig(); err != nil {
		sp.logger.WithError(err).Warn("Failed to backup current proxy config")
	}

	switch runtime.GOOS {
	case "darwin":
		return sp.setMacOSProxy(config)
	case "linux":
		return sp.setLinuxProxy(config)
	case "windows":
		return sp.setWindowsProxy(config)
	default:
		return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
	}
}

// RestoreSystemProxy 恢复系统代理设置
func (sp *SystemProxy) RestoreSystemProxy() error {
	sp.logger.Info("Restoring system proxy configuration")

	switch runtime.GOOS {
	case "darwin":
		return sp.restoreMacOSProxy()
	case "linux":
		return sp.restoreLinuxProxy()
	case "windows":
		return sp.restoreWindowsProxy()
	default:
		return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
	}
}

// setMacOSProxy 设置macOS系统代理
func (sp *SystemProxy) setMacOSProxy(config Config) error {
	// 获取所有网络服务
	services, err := sp.getMacOSNetworkServices()
	if err != nil {
		return fmt.Errorf("failed to get network services: %w", err)
	}

	for _, service := range services {
		// 设置HTTP代理
		if config.HTTPProxy != "" {
			parts := strings.Split(config.HTTPProxy, ":")
			if len(parts) == 2 {
				if err := sp.runCommand("networksetup", "-setwebproxy", service, parts[0], parts[1]); err != nil {
					sp.logger.WithError(err).WithField("service", service).Warn("Failed to set HTTP proxy")
				}
				if err := sp.runCommand("networksetup", "-setwebproxystate", service, "on"); err != nil {
					sp.logger.WithError(err).WithField("service", service).Warn("Failed to enable HTTP proxy")
				}
			}
		}

		// 设置HTTPS代理
		if config.HTTPSProxy != "" {
			parts := strings.Split(config.HTTPSProxy, ":")
			if len(parts) == 2 {
				if err := sp.runCommand("networksetup", "-setsecurewebproxy", service, parts[0], parts[1]); err != nil {
					sp.logger.WithError(err).WithField("service", service).Warn("Failed to set HTTPS proxy")
				}
				if err := sp.runCommand("networksetup", "-setsecurewebproxystate", service, "on"); err != nil {
					sp.logger.WithError(err).WithField("service", service).Warn("Failed to enable HTTPS proxy")
				}
			}
		}

		// 设置SOCKS代理
		if config.SOCKSProxy != "" {
			parts := strings.Split(config.SOCKSProxy, ":")
			if len(parts) == 2 {
				if err := sp.runCommand("networksetup", "-setsocksfirewallproxy", service, parts[0], parts[1]); err != nil {
					sp.logger.WithError(err).WithField("service", service).Warn("Failed to set SOCKS proxy")
				}
				if err := sp.runCommand("networksetup", "-setsocksfirewallproxystate", service, "on"); err != nil {
					sp.logger.WithError(err).WithField("service", service).Warn("Failed to enable SOCKS proxy")
				}
			}
		}

		// 设置代理绕过列表
		if len(config.NoProxy) > 0 {
			bypassList := strings.Join(config.NoProxy, " ")
			if err := sp.runCommand("networksetup", "-setproxybypassdomains", service, bypassList); err != nil {
				sp.logger.WithError(err).WithField("service", service).Warn("Failed to set proxy bypass list")
			}
		}
	}

	return nil
}

// setLinuxProxy 设置Linux系统代理（通过环境变量）
func (sp *SystemProxy) setLinuxProxy(config Config) error {
	envVars := make(map[string]string)

	if config.HTTPProxy != "" {
		envVars["http_proxy"] = "http://" + config.HTTPProxy
		envVars["HTTP_PROXY"] = "http://" + config.HTTPProxy
	}

	if config.HTTPSProxy != "" {
		envVars["https_proxy"] = "https://" + config.HTTPSProxy
		envVars["HTTPS_PROXY"] = "https://" + config.HTTPSProxy
	}

	if len(config.NoProxy) > 0 {
		noProxy := strings.Join(config.NoProxy, ",")
		envVars["no_proxy"] = noProxy
		envVars["NO_PROXY"] = noProxy
	}

	// 写入到用户的shell配置文件
	return sp.writeLinuxProxyConfig(envVars)
}

// setWindowsProxy 设置Windows系统代理
func (sp *SystemProxy) setWindowsProxy(config Config) error {
	// Windows代理设置通过注册表
	if config.HTTPProxy != "" {
		// 启用代理
		if err := sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "1", "/f"); err != nil {
			return fmt.Errorf("failed to enable proxy: %w", err)
		}

		// 设置代理服务器
		if err := sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyServer", "/t", "REG_SZ", "/d", config.HTTPProxy, "/f"); err != nil {
			return fmt.Errorf("failed to set proxy server: %w", err)
		}
	}

	// 设置代理绕过列表
	if len(config.NoProxy) > 0 {
		bypassList := strings.Join(config.NoProxy, ";")
		if err := sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyOverride", "/t", "REG_SZ", "/d", bypassList, "/f"); err != nil {
			return fmt.Errorf("failed to set proxy bypass list: %w", err)
		}
	}

	return nil
}

func (sp *SystemProxy) getMacOSNetworkServices() ([]string, error) {
	output, err := exec.Command("networksetup", "-listallnetworkservices").Output()
	if err != nil {
		return nil, err
	}

	lines := strings.Split(string(output), "\n")
	var services []string

	for _, line := range lines {
		line = strings.TrimSpace(line)
		if line != "" && !strings.HasPrefix(line, "*") && line != "An asterisk (*) denotes that a network service is disabled." {
			services = append(services, line)
		}
	}

	return services, nil
}

func (sp *SystemProxy) backupCurrentConfig() error {
	switch runtime.GOOS {
	case "darwin":
		return sp.backupMacOSConfig()
	case "linux":
		return sp.backupLinuxConfig()
	case "windows":
		return sp.backupWindowsConfig()
	}
	return nil
}

func (sp *SystemProxy) backupMacOSConfig() error {
	services, err := sp.getMacOSNetworkServices()
	if err != nil {
		return err
	}

	for _, service := range services {
		// 备份HTTP代理设置
		output, _ := exec.Command("networksetup", "-getwebproxy", service).Output()
		sp.backupConfig[fmt.Sprintf("http_%s", service)] = string(output)

		// 备份HTTPS代理设置
		output, _ = exec.Command("networksetup", "-getsecurewebproxy", service).Output()
		sp.backupConfig[fmt.Sprintf("https_%s", service)] = string(output)

		// 备份SOCKS代理设置
		output, _ = exec.Command("networksetup", "-getsocksfirewallproxy", service).Output()
		sp.backupConfig[fmt.Sprintf("socks_%s", service)] = string(output)
	}

	return nil
}

func (sp *SystemProxy) backupLinuxConfig() error {
	// 备份环境变量
	sp.backupConfig["http_proxy"] = os.Getenv("http_proxy")
	sp.backupConfig["https_proxy"] = os.Getenv("https_proxy")
	sp.backupConfig["no_proxy"] = os.Getenv("no_proxy")
	return nil
}

func (sp *SystemProxy) backupWindowsConfig() error {
	// 备份Windows注册表设置
	output, _ := exec.Command("reg", "query", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyEnable").Output()
	sp.backupConfig["ProxyEnable"] = string(output)

	output, _ = exec.Command("reg", "query", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyServer").Output()
	sp.backupConfig["ProxyServer"] = string(output)

	return nil
}

func (sp *SystemProxy) restoreMacOSProxy() error {
	services, err := sp.getMacOSNetworkServices()
	if err != nil {
		return err
	}

	for _, service := range services {
		// 禁用所有代理
		sp.runCommand("networksetup", "-setwebproxystate", service, "off")
		sp.runCommand("networksetup", "-setsecurewebproxystate", service, "off")
		sp.runCommand("networksetup", "-setsocksfirewallproxystate", service, "off")
	}

	return nil
}

func (sp *SystemProxy) restoreLinuxProxy() error {
	// 清除环境变量（这里简化处理）
	os.Unsetenv("http_proxy")
	os.Unsetenv("https_proxy")
	os.Unsetenv("no_proxy")
	os.Unsetenv("HTTP_PROXY")
	os.Unsetenv("HTTPS_PROXY")
	os.Unsetenv("NO_PROXY")
	return nil
}

func (sp *SystemProxy) restoreWindowsProxy() error {
	// 禁用代理
	return sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "0", "/f")
}

func (sp *SystemProxy) writeLinuxProxyConfig(envVars map[string]string) error {
	// 写入到 ~/.bashrc 和 ~/.profile
	homeDir, err := os.UserHomeDir()
	if err != nil {
		return err
	}

	configFiles := []string{
		homeDir + "/.bashrc",
		homeDir + "/.profile",
	}

	proxyLines := []string{"\n# Wormhole SOCKS5 Proxy Configuration"}
	for key, value := range envVars {
		proxyLines = append(proxyLines, fmt.Sprintf("export %s=%s", key, value))
	}
	proxyLines = append(proxyLines, "# End Wormhole Configuration\n")

	for _, configFile := range configFiles {
		file, err := os.OpenFile(configFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			sp.logger.WithError(err).WithField("file", configFile).Warn("Failed to open config file")
			continue
		}

		for _, line := range proxyLines {
			if _, err := file.WriteString(line + "\n"); err != nil {
				sp.logger.WithError(err).WithField("file", configFile).Warn("Failed to write to config file")
			}
		}

		file.Close()
	}

	return nil
}

func (sp *SystemProxy) runCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		sp.logger.WithFields(logrus.Fields{
			"command": fmt.Sprintf("%s %s", name, strings.Join(args, " ")),
			"output":  string(output),
		}).WithError(err).Debug("Command execution failed")
		return err
	}
	return nil
}

// GetCurrentConfig 获取当前系统代理配置
func (sp *SystemProxy) GetCurrentConfig() (Config, error) {
	config := Config{
		NoProxy: []string{},
	}

	switch runtime.GOOS {
	case "linux":
		config.HTTPProxy = os.Getenv("http_proxy")
		config.HTTPSProxy = os.Getenv("https_proxy")
		noProxy := os.Getenv("no_proxy")
		if noProxy != "" {
			config.NoProxy = strings.Split(noProxy, ",")
		}
	}

	return config, nil
}

// IsProxySet 检查是否已设置代理
func (sp *SystemProxy) IsProxySet() bool {
	switch runtime.GOOS {
	case "linux":
		return os.Getenv("http_proxy") != "" || os.Getenv("https_proxy") != ""
	case "darwin":
		// 检查macOS代理设置（简化）
		return false
	case "windows":
		// 检查Windows代理设置（简化）
		return false
	}
	return false
}
