// Package utils 提供通用工具函数
package utils

import (
	"fmt"
	"net"
	"strings"
)

// ParseIPAllowList 解析 IP/CIDR 白名单列表。
//
// 支持格式：
//   - CIDR 格式：192.168.1.0/24、::1/128
//   - 单个 IP：192.168.1.1（自动转换为 /32 或 /128）
//   - 特殊值 "localhost"：映射为 127.0.0.1/32 和 ::1/128
//
// 参数：
//   - allow: IP/CIDR 字符串列表
//
// 返回值：
//   - []net.IPNet: 解析后的网络列表
//   - error: 解析失败时返回错误
func ParseIPAllowList(allow []string) ([]net.IPNet, error) {
	if len(allow) == 0 {
		return nil, nil
	}

	result := make([]net.IPNet, 0, len(allow)+2) // +2 for localhost expansion

	for _, cidr := range allow {
		// 处理 localhost 特殊情况
		if cidr == "localhost" {
			// localhost 解析为 127.0.0.1 和 ::1
			if v4Net, err := parseCIDR("127.0.0.1/32"); err == nil {
				result = append(result, *v4Net)
			}
			if v6Net, err := parseCIDR("::1/128"); err == nil {
				result = append(result, *v6Net)
			}
			continue
		}

		// 尝试 CIDR 解析
		_, network, err := net.ParseCIDR(cidr)
		if err == nil && network != nil {
			result = append(result, *network)
			continue
		}

		// fallback: 尝试作为单个 IP 解析
		ip := net.ParseIP(cidr)
		if ip == nil {
			return nil, err // 返回原始 CIDR 解析错误
		}

		// 转换为 CIDR 格式
		var ipNet *net.IPNet
		if ip.To4() != nil {
			ipNet, _ = parseCIDR(cidr + "/32")
		} else {
			ipNet, _ = parseCIDR(cidr + "/128")
		}
		if ipNet != nil {
			result = append(result, *ipNet)
		}
	}

	return result, nil
}

// ParseCIDR 解析 CIDR 字符串或单个 IP 地址。
//
// 支持格式：
//   - CIDR 格式：192.168.1.0/24、::1/128
//   - 单个 IP：192.168.1.1（自动转换为 /32 或 /128）
//
// 参数：
//   - cidr: CIDR 字符串或单个 IP 地址
//
// 返回值：
//   - *net.IPNet: 解析后的 IP 网络对象
//   - error: 解析失败时返回错误
func ParseCIDR(cidr string) (*net.IPNet, error) {
	// 处理单个 IP（没有 /前缀）
	if !strings.Contains(cidr, "/") {
		ip := net.ParseIP(cidr)
		if ip == nil {
			return nil, fmt.Errorf("invalid IP address: %s", cidr)
		}

		// 转换为完整掩码的 CIDR
		if ip.To4() != nil {
			cidr = cidr + "/32"
		} else {
			cidr = cidr + "/128"
		}
	}

	// 解析 CIDR
	ip, network, err := net.ParseCIDR(cidr)
	if err != nil {
		return nil, err
	}

	// 确保 IP 为规范形式
	network.IP = ip

	return network, nil
}

// parseCIDR 是 ParseCIDR 的内部别名，保持向后兼容
func parseCIDR(cidr string) (*net.IPNet, error) {
	return ParseCIDR(cidr)
}

// IPInAllowList 检查 IP 是否在白名单中。
//
// 参数：
//   - ip: 要检查的 IP 地址
//   - allowList: 白名单网络列表
//
// 返回值：
//   - bool: IP 在白名单中返回 true
func IPInAllowList(ip net.IP, allowList []net.IPNet) bool {
	if len(allowList) == 0 {
		return false
	}
	for _, network := range allowList {
		if network.Contains(ip) {
			return true
		}
	}
	return false
}
