package client

import (
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"
	"time"

	"crypto-miner-agent/deploy"
)

func listNetInterfaces() []SysCheckInterface {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil
	}
	var out []SysCheckInterface
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue
		}
		entry := SysCheckInterface{Name: iface.Name}
		if mac := iface.HardwareAddr.String(); mac != "" {
			entry.MAC = mac
		}
		addrs, err := iface.Addrs()
		if err != nil {
			continue
		}
		for _, a := range addrs {
			switch v := a.(type) {
			case *net.IPNet:
				if ip4 := v.IP.To4(); ip4 != nil {
					entry.IPv4 = append(entry.IPv4, fmt.Sprintf("%s/%d", ip4.String(), ones(v.Mask)))
				} else if v.IP != nil && v.IP.To4() == nil {
					entry.IPv6 = append(entry.IPv6, v.IP.String())
				}
			}
		}
		if len(entry.IPv4) > 0 || len(entry.IPv6) > 0 || entry.MAC != "" {
			out = append(out, entry)
		}
	}
	return out
}

func ones(mask net.IPMask) int {
	n, _ := mask.Size()
	return n
}

func fetchExternalIP() (ip, source string) {
	client := &http.Client{Timeout: 6 * time.Second}
	services := []struct {
		url    string
		source string
	}{
		{"https://api.ipify.org", "ipify"},
		{"https://icanhazip.com", "icanhazip"},
		{"https://ifconfig.me/ip", "ifconfig.me"},
	}
	for _, svc := range services {
		resp, err := client.Get(svc.url)
		if err != nil {
			continue
		}
		body, err := io.ReadAll(io.LimitReader(resp.Body, 64))
		resp.Body.Close()
		if err != nil || resp.StatusCode != http.StatusOK {
			continue
		}
		candidate := strings.TrimSpace(string(body))
		if parsed := net.ParseIP(candidate); parsed != nil && parsed.To4() != nil {
			return candidate, svc.source
		}
	}
	if wan, err := deploy.GetPublicEndpoint(); err == nil && wan != "" {
		return wan, "upnp"
	}
	return "", ""
}

func fetchGeo(ip string) *SysCheckGeo {
	if ip == "" {
		return nil
	}
	url := fmt.Sprintf("http://ip-api.com/json/%s?fields=status,message,query,country,regionName,city,lat,lon,isp,org", ip)
	client := &http.Client{Timeout: 8 * time.Second}
	resp, err := client.Get(url)
	if err != nil {
		return nil
	}
	defer resp.Body.Close()
	data, err := io.ReadAll(io.LimitReader(resp.Body, 4096))
	if err != nil {
		return nil
	}
	var m map[string]interface{}
	if json.Unmarshal(data, &m) != nil {
		return nil
	}
	if s, _ := m["status"].(string); s != "success" {
		return nil
	}
	g := &SysCheckGeo{Query: ip}
	if v, ok := m["country"].(string); ok {
		g.Country = v
	}
	if v, ok := m["regionName"].(string); ok {
		g.Region = v
	}
	if v, ok := m["city"].(string); ok {
		g.City = v
	}
	if v, ok := m["isp"].(string); ok {
		g.ISP = v
	}
	if v, ok := m["org"].(string); ok {
		g.Org = v
	}
	if v, ok := m["lat"].(float64); ok {
		g.Lat = v
	}
	if v, ok := m["lon"].(float64); ok {
		g.Lon = v
	}
	return g
}
