package host_info

import (
	"agent-wdd/log"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"regexp"
	"time"
)

// 能够联网,就大于这个数字  外网9 国内7 不能联网1 未知0
const InternetBaseLine = 1

// 定义响应数据结构体
type IPInfo struct {
	IP       string `json:"ip"`
	City     string `json:"city"`
	Region   string `json:"region"`
	Country  string `json:"country"`
	Loc      string `json:"loc"`
	Org      string `json:"org"`
	Postal   string `json:"postal"`
	Timezone string `json:"timezone"`
}

// Gather 获取网络相关的信息
func (network *Network) Gather() {

	log.Info("Gathering INFO => NETWORK !")
	// 能够联网
	network.Internet = CanConnectInternet()

	// 获取公网的相关信息
	network.Public = network.Public.GetPublicInfo()

	//获取本机网卡相关的内容
	network.Interfaces = GetInterfaces()
}

// GetInterfaces 获取本机网卡相关的内容
func GetInterfaces() []Interface {
	interfaces := []Interface{}

	// 获取所有网卡信息
	netInterfaces, err := net.Interfaces()
	// log.Info("all network interfaces: %v", netInterfaces)
	if err != nil {
		log.Error("获取网卡信息失败: %v", err)
		return interfaces
	}

	for _, netInterface := range netInterfaces {
		// 过滤掉没有地址的网卡
		addrs, err := netInterface.Addrs()
		if err != nil || len(addrs) == 0 {
			continue
		}

		// 检查网卡名称是否有效
		if !isValidNICName(netInterface.Name) {
			continue
		}

		// 创建 Interface 对象
		iface := Interface{
			Name: netInterface.Name,
			MAC:  netInterface.HardwareAddr.String(),
			MTU:  netInterface.MTU,
		}

		// 获取 IPv4 和 IPv6 地址
		for _, addr := range addrs {
			ipNet, ok := addr.(*net.IPNet)
			if !ok {
				continue
			}

			if ipNet.IP.To4() != nil {
				iface.IPv4 = ipNet.IP.String()
			} else if ipNet.IP.To16() != nil {
				iface.IPv6 = ipNet.IP.String()
			}
		}

		interfaces = append(interfaces, iface)
	}

	return interfaces
}

func (network *Network) SaveConfig() {

	ConfigCache.Agent.Network = *network
	SaveConfig()
}

// CanConnectInternet 判定主机能够上网 外网为9 国内为7 不能上网为1
func CanConnectInternet() int {

	// 读取 config 文件，判定能否上网
	internetCode := ConfigCache.Agent.Network.Internet

	if internetCode == 0 {
		// 没有相关的信息,需要重新判定
		internetCode = judgeCanConnectInternet()

		// 持久化保存
		ConfigCache.Agent.Network.Internet = internetCode
	}

	return internetCode
}

// judgeCanConnectInternet 请求网址判定主机能否上网 请求 www.google.com 如果请求正常 返回9 如果超时三秒 请求baidu.com，如果没有错误返回7 如果错误返回1
func judgeCanConnectInternet() int {
	client := http.Client{
		Timeout: 3 * time.Second,
	}

	results := make(chan int, 2)

	go func() {
		_, err := client.Get("https://www.google.com")
		if err == nil {
			results <- 9
		} else {
			results <- 1
		}
	}()

	go func() {
		_, err := client.Get("https://www.baidu.com")
		if err == nil {
			results <- 7
		} else {
			results <- 1
		}
	}()

	maxResult := 1
	for i := 0; i < 2; i++ {
		result := <-results
		if result > maxResult {
			maxResult = result
		}
	}

	return maxResult
}

// GetPublicInfo 获取服务器的公网信息
func (p PublicInfo) GetPublicInfo() PublicInfo {

	// 无法联网, 假信息

	fakePublicInfo := PublicInfo{
		IPv4:     "1.1.1.1",
		IPv6:     "2400::1",
		Country:  "CN",
		City:     "Shanghai",
		ASN:      "Wdd Inc",
		Timezone: "Asia/Shanghai",
	}

	if CanConnectInternet() == InternetBaseLine {

		// 持久化保存
		ConfigCache.Agent.Network.Public = fakePublicInfo

		return fakePublicInfo
	}

	// 可以联网
	// 创建带有超时的HTTP客户端
	client := &http.Client{
		Timeout: 3 * time.Second,
	}

	// 创建新的请求对象
	req, err := http.NewRequest("GET", "https://ipinfo.io", nil)
	if err != nil {
		log.Error("创建请求失败: %v", err)
		return fakePublicInfo

	}

	// 设置请求头
	req.Header.Add("Authorization", "Bearer 6ecb0db9bd8f19")
	req.Header.Add("Accept", "application/json")

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		log.Error("请求PublicInfo失败: %s", err.Error())
		return fakePublicInfo
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		log.Error("非200状态码: %d", resp.StatusCode)
	}

	// 读取响应体
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Error("读取响应失败: %v", err)
	}

	// 解析JSON数据
	var info IPInfo
	if err := json.Unmarshal(body, &info); err != nil {
		log.Error("JSON解析失败: %v", err)
	}

	// 打印解析结果
	// log.Info("IP信息:\n%+v\n", info)

	// 保存信息
	p.IPv4 = info.IP
	p.ASN = info.Org
	p.Country = info.Country
	p.City = info.City
	p.Timezone = info.Timezone

	ConfigCache.Agent.Network.Public = p

	return p
}

func isValidNICName(name string) bool {
	// 定义传统命名规则正则表达式
	// eth0, eth1, wlan0, wlan1 等
	traditionalPattern := `^(eth|wlan)[0-9]+$`

	// 定义现代命名规则正则表达式
	// 支持 eno1, ens3, enp0s3, enx<MAC>, wlp2s0 等格式
	modernPattern := `^(en|wl)(o[0-9]+|s[0-9]+|p[0-9]+s[0-9]+|x[0-9a-fA-F]{12})$`

	// 编译正则表达式
	traditionalRegex := regexp.MustCompile(traditionalPattern)
	modernRegex := regexp.MustCompile(modernPattern)

	// 检查是否匹配传统命名或现代命名规则
	return traditionalRegex.MatchString(name) || modernRegex.MatchString(name)
}

func main() {
	// 测试用例
	testCases := []string{
		"eth0",            // 传统以太网命名
		"wlan1",           // 传统无线网卡命名
		"eno1",            // 板载网卡
		"ens3",            // 插槽网卡
		"enp0s3",          // PCI网卡
		"enx0a1b2c3d4e5f", // 基于MAC地址的命名
		"wlp2s0",          // 无线PCI网卡
		"eth",             // 无效：缺少数字
		"enp0",            // 无效：不符合现代规则
		"abc123",          // 无效：完全不匹配
	}

	for _, tc := range testCases {
		if isValidNICName(tc) {
			fmt.Printf("%s: 有效网卡名称\n", tc)
		} else {
			fmt.Printf("%s: 无效网卡名称\n", tc)
		}
	}
}
