//
//  Util.swift
//  Tun
//
//  Created by 安礼成 on 2024/1/19.
//

import Foundation
import SystemConfiguration
import Darwin

struct SDLUtil {
    
    public static func int32ToIp(_ num: UInt32) -> String {
        let ip0 = (UInt8) (num >> 24 & 0xFF)
        let ip1 = (UInt8) (num >> 16 & 0xFF)
        let ip2 = (UInt8) (num >> 8 & 0xFF)
        let ip3 = (UInt8) (num & 0xFF)
        
        return "\(ip0).\(ip1).\(ip2).\(ip3)"
    }
    
    public static func netMaskIp(maskLen: UInt8) -> String {
        let len0 = 32 - maskLen
        let num: UInt32 = (0xFFFFFFFF >> len0) << len0
        
        let ip0 = (UInt8) (num >> 24 & 0xFF)
        let ip1 = (UInt8) (num >> 16 & 0xFF)
        let ip2 = (UInt8) (num >> 8 & 0xFF)
        let ip3 = (UInt8) (num & 0xFF)
        
        return "\(ip0).\(ip1).\(ip2).\(ip3)"
    }
    
    public static func ipv4StrToInt32(_ ip: String) -> UInt32? {
        let parts = ip.split(separator: ".")
        guard parts.count == 4 else {
            return nil
        }
        
        var result: UInt32 = 0
        for part in parts {
            guard let byte = UInt8(part) else { return nil }
            result = (result << 8) | UInt32(byte)
        }
        
        return result
    }

    public static func ipv6DataToString(_ data: Data) -> String? {
        guard data.count == 16 else {
            return nil
        }
        
        return data.withUnsafeBytes { rawBuffer in
            guard let baseAddress = rawBuffer.baseAddress else {
                return nil
            }
            
            var hostBuffer = [CChar](repeating: 0, count: Int(INET6_ADDRSTRLEN))
            guard inet_ntop(AF_INET6, baseAddress, &hostBuffer, socklen_t(INET6_ADDRSTRLEN)) != nil else {
                return nil
            }
            
            return String(cString: hostBuffer)
        }
    }

    public static func ipv6StrToData(_ ip: String) -> Data? {
        let normalizedIp = String(ip.split(separator: "%", maxSplits: 1, omittingEmptySubsequences: false).first ?? "")
        guard !normalizedIp.isEmpty else {
            return nil
        }
        
        var address = in6_addr()
        guard inet_pton(AF_INET6, normalizedIp, &address) == 1 else {
            return nil
        }
        
        return withUnsafeBytes(of: &address) { Data($0) }
    }
    
    // 判断ip地址是否在同一个网络
    public static func inSameNetwork(ip: UInt32, compareIp: UInt32, maskLen: UInt8) -> Bool {
        if ip == compareIp {
            return true
        }
        
        let len0 = 32 - maskLen
        // 掩码值
        let mask: UInt32 = (0xFFFFFFFF >> len0) << len0
            
        return ip & mask == compareIp & mask
    }
    
    public static func formatMacAddress(mac: Data) -> String {
        let bytes = [UInt8](mac)
        
        return bytes.map { String(format: "%02X", $0) }.joined(separator: ":").lowercased()
    }
    
    public static func getMacOSSystemDnsServers() -> [String] {
        var results = [String]()
        
        // 获取全局 DNS 配置
        if let dict = SCDynamicStoreCopyValue(nil, "State:/Network/Global/DNS" as CFString) as? [String: Any] {
            if let servers = dict["ServerAddresses"] as? [String] {
                results = servers
            }
        }
        return results
    }
}
