package util

import (
	"net"
	"strings"

	"github.com/kataras/iris/v12"
)

// 收集的内网网络地址 IP 段
var localNetworks []*net.IPNet

func init() {
	localNetworks = make([]*net.IPNet, 4)
	for i, sNetwork := range []string{
		"10.0.0.0/8",
		"169.254.0.0/16",
		"172.16.0.0/12",
		"192.168.0.0/16",
	} {
		_, network, _ := net.ParseCIDR(sNetwork)
		localNetworks[i] = network
	}
}

// 获取客户端IP
func ClientIP(ctx iris.Context) string {
	// 反向代理IP
	xForwardedFor := ctx.GetHeader("X-Forwarded-For")
	ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
	if ip != "" {
		return ip
	}

	// 反向代理IP
	ip = strings.TrimSpace(ctx.GetHeader("X-Real-Ip"))
	if ip != "" {
		return ip
	}

	// 客户端IP
	if ip, _, err := net.SplitHostPort(strings.TrimSpace(ctx.RemoteAddr())); err == nil {
		return ip
	}

	return ""
}

// 获取公网IP
func ClientPublicIP(ctx iris.Context) string {
	var ip string
	for _, ip = range strings.Split(ctx.GetHeader("X-Forwarded-For"), ",") {
		ip = strings.TrimSpace(ip)
		if ip != "" && !HasLocalIPddr(ip) {
			return ip
		}
	}

	ip = strings.TrimSpace(ctx.GetHeader("X-Real-Ip"))
	if ip != "" && !HasLocalIPddr(ip) {
		return ip
	}

	if ip, _, err := net.SplitHostPort(strings.TrimSpace(ctx.RemoteAddr())); err == nil {
		if !HasLocalIPddr(ip) {
			return ip
		}
	}

	return ""
}

// RemoteIP 通过 RemoteAddr 获取 IP 地址， 只是一个快速解析方法。
func RemoteIP(ctx iris.Context) string {
	if ip, _, err := net.SplitHostPort(strings.TrimSpace(ctx.RemoteAddr())); err == nil {
		return ip
	}

	return ""
}

// HasLocalIPddr 检测 IP 地址字符串是否是内网地址
func HasLocalIPddr(ip string) bool {
	return HasLocalIP(net.ParseIP(ip))
}

// 检测 IP 地址是否是内网地址
func HasLocalIP(ip net.IP) bool {
	for _, network := range localNetworks {
		if network.Contains(ip) {
			return true
		}
	}

	return ip.IsLoopback()
}
