import Darwin
import Foundation
import SystemConfiguration

private let systemConfigurationHandle: UnsafeMutableRawPointer? = {
    let path = "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
    return dlopen(path, RTLD_LAZY | RTLD_NOLOAD) ?? dlopen(path, RTLD_LAZY)
}()

private func stringConstant(named name: String) -> String? {
    guard let handle = systemConfigurationHandle,
          let symbol = dlsym(handle, name),
          let raw = symbol.assumingMemoryBound(to: UnsafeRawPointer?.self).pointee
    else {
        return nil
    }

    let value = unsafeBitCast(raw, to: CFString.self)
    return value as String
}

private func schemaSubset(_ all: [String: String], _ entries: [(String, String)]) -> [String: String] {
    Dictionary(uniqueKeysWithValues: entries.compactMap { alias, symbol in
        all[symbol].map { (alias, $0) }
    })
}

private let allSchemaConstantNames = [
    "kSCResvLink",
    "kSCResvInactive",
    "kSCPropInterfaceName",
    "kSCPropMACAddress",
    "kSCPropUserDefinedName",
    "kSCPropVersion",
    "kSCPrefCurrentSet",
    "kSCPrefNetworkServices",
    "kSCPrefSets",
    "kSCPrefSystem",
    "kSCCompNetwork",
    "kSCCompService",
    "kSCCompGlobal",
    "kSCCompHostNames",
    "kSCCompInterface",
    "kSCCompSystem",
    "kSCCompUsers",
    "kSCCompAnyRegex",
    "kSCEntNetAirPort",
    "kSCEntNetDHCP",
    "kSCEntNetDNS",
    "kSCEntNetEthernet",
    "kSCEntNetFireWire",
    "kSCEntNetInterface",
    "kSCEntNetIPSec",
    "kSCEntNetIPv4",
    "kSCEntNetIPv6",
    "kSCEntNetL2TP",
    "kSCEntNetLink",
    "kSCEntNetModem",
    "kSCEntNetPPP",
    "kSCEntNetPPPoE",
    "kSCEntNetPPPSerial",
    "kSCEntNetPPTP",
    "kSCEntNetProxies",
    "kSCEntNetSMB",
    "kSCEntNet6to4",
    "kSCPropNetOverridePrimary",
    "kSCPropNetServiceOrder",
    "kSCPropNetPPPOverridePrimary",
    "kSCPropNetInterfaces",
    "kSCPropNetLocalHostName",
    "kSCPropNetAirPortAllowNetCreation",
    "kSCPropNetAirPortAuthPassword",
    "kSCPropNetAirPortAuthPasswordEncryption",
    "kSCPropNetAirPortJoinMode",
    "kSCPropNetAirPortPowerEnabled",
    "kSCPropNetAirPortPreferredNetwork",
    "kSCPropNetAirPortSavePasswords",
    "kSCValNetAirPortJoinModeAutomatic",
    "kSCValNetAirPortJoinModePreferred",
    "kSCValNetAirPortJoinModeRanked",
    "kSCValNetAirPortJoinModeRecent",
    "kSCValNetAirPortJoinModeStrongest",
    "kSCValNetAirPortAuthPasswordEncryptionKeychain",
    "kSCPropNetDNSDomainName",
    "kSCPropNetDNSOptions",
    "kSCPropNetDNSSearchDomains",
    "kSCPropNetDNSSearchOrder",
    "kSCPropNetDNSServerAddresses",
    "kSCPropNetDNSServerPort",
    "kSCPropNetDNSServerTimeout",
    "kSCPropNetDNSSortList",
    "kSCPropNetDNSSupplementalMatchDomains",
    "kSCPropNetDNSSupplementalMatchOrders",
    "kSCPropNetEthernetMediaSubType",
    "kSCPropNetEthernetMediaOptions",
    "kSCPropNetEthernetMTU",
    "kSCPropNetInterfaceDeviceName",
    "kSCPropNetInterfaceHardware",
    "kSCPropNetInterfaceType",
    "kSCPropNetInterfaceSubType",
    "kSCPropNetInterfaceSupportsModemOnHold",
    "kSCValNetInterfaceTypeEthernet",
    "kSCValNetInterfaceTypeFireWire",
    "kSCValNetInterfaceTypePPP",
    "kSCValNetInterfaceType6to4",
    "kSCValNetInterfaceTypeIPSec",
    "kSCValNetInterfaceSubTypePPPoE",
    "kSCValNetInterfaceSubTypePPPSerial",
    "kSCValNetInterfaceSubTypePPTP",
    "kSCValNetInterfaceSubTypeL2TP",
    "kSCPropNetIPSecAuthenticationMethod",
    "kSCPropNetIPSecLocalCertificate",
    "kSCPropNetIPSecLocalIdentifier",
    "kSCPropNetIPSecLocalIdentifierType",
    "kSCPropNetIPSecSharedSecret",
    "kSCPropNetIPSecSharedSecretEncryption",
    "kSCPropNetIPSecConnectTime",
    "kSCPropNetIPSecRemoteAddress",
    "kSCPropNetIPSecStatus",
    "kSCPropNetIPSecXAuthEnabled",
    "kSCPropNetIPSecXAuthName",
    "kSCPropNetIPSecXAuthPassword",
    "kSCPropNetIPSecXAuthPasswordEncryption",
    "kSCValNetIPSecAuthenticationMethodSharedSecret",
    "kSCValNetIPSecAuthenticationMethodCertificate",
    "kSCValNetIPSecAuthenticationMethodHybrid",
    "kSCValNetIPSecLocalIdentifierTypeKeyID",
    "kSCValNetIPSecSharedSecretEncryptionKeychain",
    "kSCValNetIPSecXAuthPasswordEncryptionKeychain",
    "kSCValNetIPSecXAuthPasswordEncryptionPrompt",
    "kSCPropNetIPv4Addresses",
    "kSCPropNetIPv4ConfigMethod",
    "kSCPropNetIPv4DHCPClientID",
    "kSCPropNetIPv4Router",
    "kSCPropNetIPv4SubnetMasks",
    "kSCPropNetIPv4DestAddresses",
    "kSCPropNetIPv4BroadcastAddresses",
    "kSCValNetIPv4ConfigMethodAutomatic",
    "kSCValNetIPv4ConfigMethodBOOTP",
    "kSCValNetIPv4ConfigMethodDHCP",
    "kSCValNetIPv4ConfigMethodINFORM",
    "kSCValNetIPv4ConfigMethodLinkLocal",
    "kSCValNetIPv4ConfigMethodManual",
    "kSCValNetIPv4ConfigMethodPPP",
    "kSCPropNetIPv6Addresses",
    "kSCPropNetIPv6ConfigMethod",
    "kSCPropNetIPv6DestAddresses",
    "kSCPropNetIPv6Flags",
    "kSCPropNetIPv6PrefixLength",
    "kSCPropNetIPv6Router",
    "kSCValNetIPv6ConfigMethodAutomatic",
    "kSCValNetIPv6ConfigMethodLinkLocal",
    "kSCValNetIPv6ConfigMethodManual",
    "kSCValNetIPv6ConfigMethodRouterAdvertisement",
    "kSCValNetIPv6ConfigMethod6to4",
    "kSCPropNet6to4Relay",
    "kSCPropNetLinkActive",
    "kSCPropNetLinkDetaching",
    "kSCPropNetModemAccessPointName",
    "kSCPropNetModemConnectionPersonality",
    "kSCPropNetModemConnectionScript",
    "kSCPropNetModemConnectSpeed",
    "kSCPropNetModemDataCompression",
    "kSCPropNetModemDeviceContextID",
    "kSCPropNetModemDeviceModel",
    "kSCPropNetModemDeviceVendor",
    "kSCPropNetModemDialMode",
    "kSCPropNetModemErrorCorrection",
    "kSCPropNetModemHoldCallWaitingAudibleAlert",
    "kSCPropNetModemHoldDisconnectOnAnswer",
    "kSCPropNetModemHoldEnabled",
    "kSCPropNetModemHoldReminder",
    "kSCPropNetModemHoldReminderTime",
    "kSCPropNetModemNote",
    "kSCPropNetModemPulseDial",
    "kSCPropNetModemSpeaker",
    "kSCPropNetModemSpeed",
    "kSCValNetModemDialModeIgnoreDialTone",
    "kSCValNetModemDialModeManual",
    "kSCValNetModemDialModeWaitForDialTone",
    "kSCPropNetPPPACSPEnabled",
    "kSCPropNetPPPConnectTime",
    "kSCPropNetPPPDeviceLastCause",
    "kSCPropNetPPPDialOnDemand",
    "kSCPropNetPPPDisconnectOnFastUserSwitch",
    "kSCPropNetPPPDisconnectOnIdle",
    "kSCPropNetPPPDisconnectOnIdleTimer",
    "kSCPropNetPPPDisconnectOnLogout",
    "kSCPropNetPPPDisconnectOnSleep",
    "kSCPropNetPPPDisconnectTime",
    "kSCPropNetPPPIdleReminder",
    "kSCPropNetPPPIdleReminderTimer",
    "kSCPropNetPPPLastCause",
    "kSCPropNetPPPLogfile",
    "kSCPropNetPPPPlugins",
    "kSCPropNetPPPRetryConnectTime",
    "kSCPropNetPPPSessionTimer",
    "kSCPropNetPPPStatus",
    "kSCPropNetPPPUseSessionTimer",
    "kSCPropNetPPPVerboseLogging",
    "kSCPropNetPPPAuthEAPPlugins",
    "kSCPropNetPPPAuthName",
    "kSCPropNetPPPAuthPassword",
    "kSCPropNetPPPAuthPasswordEncryption",
    "kSCPropNetPPPAuthPrompt",
    "kSCPropNetPPPAuthProtocol",
    "kSCValNetPPPAuthPasswordEncryptionKeychain",
    "kSCValNetPPPAuthPasswordEncryptionToken",
    "kSCValNetPPPAuthPromptBefore",
    "kSCValNetPPPAuthPromptAfter",
    "kSCValNetPPPAuthProtocolCHAP",
    "kSCValNetPPPAuthProtocolEAP",
    "kSCValNetPPPAuthProtocolMSCHAP1",
    "kSCValNetPPPAuthProtocolMSCHAP2",
    "kSCValNetPPPAuthProtocolPAP",
    "kSCPropNetPPPCommAlternateRemoteAddress",
    "kSCPropNetPPPCommConnectDelay",
    "kSCPropNetPPPCommDisplayTerminalWindow",
    "kSCPropNetPPPCommRedialCount",
    "kSCPropNetPPPCommRedialEnabled",
    "kSCPropNetPPPCommRedialInterval",
    "kSCPropNetPPPCommRemoteAddress",
    "kSCPropNetPPPCommTerminalScript",
    "kSCPropNetPPPCommUseTerminalScript",
    "kSCPropNetPPPCCPEnabled",
    "kSCPropNetPPPCCPMPPE40Enabled",
    "kSCPropNetPPPCCPMPPE128Enabled",
    "kSCPropNetPPPIPCPCompressionVJ",
    "kSCPropNetPPPIPCPUsePeerDNS",
    "kSCPropNetPPPLCPEchoEnabled",
    "kSCPropNetPPPLCPEchoFailure",
    "kSCPropNetPPPLCPEchoInterval",
    "kSCPropNetPPPLCPCompressionACField",
    "kSCPropNetPPPLCPCompressionPField",
    "kSCPropNetPPPLCPMRU",
    "kSCPropNetPPPLCPMTU",
    "kSCPropNetPPPLCPReceiveACCM",
    "kSCPropNetPPPLCPTransmitACCM",
    "kSCPropNetL2TPIPSecSharedSecret",
    "kSCPropNetL2TPIPSecSharedSecretEncryption",
    "kSCPropNetL2TPTransport",
    "kSCValNetL2TPIPSecSharedSecretEncryptionKeychain",
    "kSCValNetL2TPTransportIP",
    "kSCValNetL2TPTransportIPSec",
    "kSCPropNetProxiesExceptionsList",
    "kSCPropNetProxiesExcludeSimpleHostnames",
    "kSCPropNetProxiesFTPEnable",
    "kSCPropNetProxiesFTPPassive",
    "kSCPropNetProxiesFTPPort",
    "kSCPropNetProxiesFTPProxy",
    "kSCPropNetProxiesFTPUser",
    "kSCPropNetProxiesGopherEnable",
    "kSCPropNetProxiesGopherPort",
    "kSCPropNetProxiesGopherProxy",
    "kSCPropNetProxiesGopherUser",
    "kSCPropNetProxiesHTTPEnable",
    "kSCPropNetProxiesHTTPPort",
    "kSCPropNetProxiesHTTPProxy",
    "kSCPropNetProxiesHTTPUser",
    "kSCPropNetProxiesHTTPSEnable",
    "kSCPropNetProxiesHTTPSPort",
    "kSCPropNetProxiesHTTPSProxy",
    "kSCPropNetProxiesHTTPSUser",
    "kSCPropNetProxiesRTSPEnable",
    "kSCPropNetProxiesRTSPPort",
    "kSCPropNetProxiesRTSPProxy",
    "kSCPropNetProxiesRTSPUser",
    "kSCPropNetProxiesSOCKSEnable",
    "kSCPropNetProxiesSOCKSPort",
    "kSCPropNetProxiesSOCKSProxy",
    "kSCPropNetProxiesSOCKSUser",
    "kSCPropNetProxiesProxyAutoConfigEnable",
    "kSCPropNetProxiesProxyAutoConfigJavaScript",
    "kSCPropNetProxiesProxyAutoConfigURLString",
    "kSCPropNetProxiesProxyAutoDiscoveryEnable",
    "kSCPropNetSMBNetBIOSName",
    "kSCPropNetSMBNetBIOSNodeType",
    "kSCPropNetSMBNetBIOSScope",
    "kSCPropNetSMBWINSAddresses",
    "kSCPropNetSMBWorkgroup",
    "kSCValNetSMBNetBIOSNodeTypeBroadcast",
    "kSCValNetSMBNetBIOSNodeTypePeer",
    "kSCValNetSMBNetBIOSNodeTypeMixed",
    "kSCValNetSMBNetBIOSNodeTypeHybrid",
    "kSCEntUsersConsoleUser",
    "kSCPropSystemComputerName",
    "kSCPropSystemComputerNameEncoding",
    "kSCDynamicStoreDomainFile",
    "kSCDynamicStoreDomainPlugin",
    "kSCDynamicStoreDomainSetup",
    "kSCDynamicStoreDomainState",
    "kSCDynamicStoreDomainPrefs",
    "kSCDynamicStorePropSetupCurrentSet",
    "kSCDynamicStorePropSetupLastUpdated",
    "kSCDynamicStorePropNetInterfaces",
    "kSCDynamicStorePropNetPrimaryInterface",
    "kSCDynamicStorePropNetPrimaryService",
    "kSCDynamicStorePropNetServiceIDs",
    "kSCPropUsersConsoleUserName",
    "kSCPropUsersConsoleUserUID",
    "kSCPropUsersConsoleUserGID",
]

@_cdecl("sc_schema_copy_catalog")
public func sc_schema_copy_catalog() -> UnsafeMutableRawPointer? {
    let all = Dictionary(uniqueKeysWithValues: allSchemaConstantNames.compactMap { name in
        stringConstant(named: name).map { (name, $0) }
    })
    let payload: [String: Any] = [
        "all": all,
        "reserved": schemaSubset(all, [
            ("link", "kSCResvLink"),
            ("inactive", "kSCResvInactive"),
        ]),
        "preferences": schemaSubset(all, [
            ("current_set", "kSCPrefCurrentSet"),
            ("network_services", "kSCPrefNetworkServices"),
            ("sets", "kSCPrefSets"),
            ("system", "kSCPrefSystem"),
        ]),
        "components": schemaSubset(all, [
            ("network", "kSCCompNetwork"),
            ("service", "kSCCompService"),
            ("global", "kSCCompGlobal"),
            ("host_names", "kSCCompHostNames"),
            ("interface", "kSCCompInterface"),
            ("system", "kSCCompSystem"),
            ("users", "kSCCompUsers"),
            ("any_regex", "kSCCompAnyRegex"),
        ]),
        "entities": schemaSubset(all, [
            ("airport", "kSCEntNetAirPort"),
            ("dhcp", "kSCEntNetDHCP"),
            ("dns", "kSCEntNetDNS"),
            ("ethernet", "kSCEntNetEthernet"),
            ("interface", "kSCEntNetInterface"),
            ("ipsec", "kSCEntNetIPSec"),
            ("ipv4", "kSCEntNetIPv4"),
            ("ipv6", "kSCEntNetIPv6"),
            ("l2tp", "kSCEntNetL2TP"),
            ("link", "kSCEntNetLink"),
            ("modem", "kSCEntNetModem"),
            ("ppp", "kSCEntNetPPP"),
            ("pppoe", "kSCEntNetPPPoE"),
            ("pptp", "kSCEntNetPPTP"),
            ("proxies", "kSCEntNetProxies"),
            ("smb", "kSCEntNetSMB"),
            ("six_to_four", "kSCEntNet6to4"),
        ]),
        "generic_properties": schemaSubset(all, [
            ("interface_name", "kSCPropInterfaceName"),
            ("mac_address", "kSCPropMACAddress"),
            ("user_defined_name", "kSCPropUserDefinedName"),
            ("version", "kSCPropVersion"),
        ]),
        "ipv4": schemaSubset(all, [
            ("addresses", "kSCPropNetIPv4Addresses"),
            ("config_method", "kSCPropNetIPv4ConfigMethod"),
            ("dhcp_client_id", "kSCPropNetIPv4DHCPClientID"),
            ("router", "kSCPropNetIPv4Router"),
            ("subnet_masks", "kSCPropNetIPv4SubnetMasks"),
            ("automatic", "kSCValNetIPv4ConfigMethodAutomatic"),
            ("bootp", "kSCValNetIPv4ConfigMethodBOOTP"),
            ("dhcp", "kSCValNetIPv4ConfigMethodDHCP"),
            ("inform", "kSCValNetIPv4ConfigMethodINFORM"),
            ("link_local", "kSCValNetIPv4ConfigMethodLinkLocal"),
            ("manual", "kSCValNetIPv4ConfigMethodManual"),
            ("ppp", "kSCValNetIPv4ConfigMethodPPP"),
        ]),
        "ipv6": schemaSubset(all, [
            ("addresses", "kSCPropNetIPv6Addresses"),
            ("config_method", "kSCPropNetIPv6ConfigMethod"),
            ("router", "kSCPropNetIPv6Router"),
            ("automatic", "kSCValNetIPv6ConfigMethodAutomatic"),
            ("link_local", "kSCValNetIPv6ConfigMethodLinkLocal"),
            ("manual", "kSCValNetIPv6ConfigMethodManual"),
            ("router_advertisement", "kSCValNetIPv6ConfigMethodRouterAdvertisement"),
            ("six_to_four", "kSCValNetIPv6ConfigMethod6to4"),
        ]),
        "dns": schemaSubset(all, [
            ("domain_name", "kSCPropNetDNSDomainName"),
            ("options", "kSCPropNetDNSOptions"),
            ("search_domains", "kSCPropNetDNSSearchDomains"),
            ("server_addresses", "kSCPropNetDNSServerAddresses"),
            ("server_port", "kSCPropNetDNSServerPort"),
        ]),
        "proxies": schemaSubset(all, [
            ("exceptions_list", "kSCPropNetProxiesExceptionsList"),
            ("http_enable", "kSCPropNetProxiesHTTPEnable"),
            ("http_proxy", "kSCPropNetProxiesHTTPProxy"),
            ("http_port", "kSCPropNetProxiesHTTPPort"),
            ("https_enable", "kSCPropNetProxiesHTTPSEnable"),
            ("https_proxy", "kSCPropNetProxiesHTTPSProxy"),
            ("https_port", "kSCPropNetProxiesHTTPSPort"),
            ("socks_enable", "kSCPropNetProxiesSOCKSEnable"),
            ("socks_proxy", "kSCPropNetProxiesSOCKSProxy"),
            ("socks_port", "kSCPropNetProxiesSOCKSPort"),
        ]),
        "interface_types": schemaSubset(all, [
            ("ethernet", "kSCValNetInterfaceTypeEthernet"),
            ("firewire", "kSCValNetInterfaceTypeFireWire"),
            ("ppp", "kSCValNetInterfaceTypePPP"),
            ("six_to_four", "kSCValNetInterfaceType6to4"),
            ("ipsec", "kSCValNetInterfaceTypeIPSec"),
            ("pppoe", "kSCValNetInterfaceSubTypePPPoE"),
            ("ppp_serial", "kSCValNetInterfaceSubTypePPPSerial"),
            ("pptp", "kSCValNetInterfaceSubTypePPTP"),
            ("l2tp", "kSCValNetInterfaceSubTypeL2TP"),
        ])
    ]

    return boxString(jsonString(from: payload))
}
