package com.admanager;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Hashtable;

public class ADLdapConnectorT implements AutoCloseable {

    private LdapContext ldapContext;
    private String domain;
    private String ldapUrl;

    public ADLdapConnectorT(String domain, String ldapUrl) {
        this.domain = domain;
        this.ldapUrl = ldapUrl;
    }

    public void connect(String username, String password) throws NamingException {
        Hashtable<String, String> env = new Hashtable<>();

        // 设置连接参数
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, ldapUrl);
        env.put(Context.SECURITY_AUTHENTICATION, "simple");

        // 格式为: username@domain 或 domain\\username
        env.put(Context.SECURITY_PRINCIPAL, "TLCT\\adadministrator");
        env.put(Context.SECURITY_CREDENTIALS, password);

        // 可选：设置领域(realm)
        env.put("java.naming.security.sasl.realm", "tlct.com.cn");

        // 其他可选设置
//        env.put("java.naming.ldap.version", "3");
//        env.put("java.naming.ldap.attributes.binary", "objectGUID");

        // 建立连接
        this.ldapContext = new InitialLdapContext(env, null);
        System.out.println("成功连接到AD域: " + domain);
    }

    public void close() throws NamingException {
        if (ldapContext != null) {
            ldapContext.close();
            System.out.println("连接已关闭");
        }
    }

    public static void main(String[] args) {
        // 配置AD域信息
        String domain = "tlct.com.cn";
        String ldapUrl = "ldap://admserver.tlct.com.cn:389";
        String username = "TLCT\\adadministrator";
        System.err.println(username);
        String password = "yonyou@123";
        String baseDn = "dc=tlct,dc=com,dc=cn";
        // 1. 首先测试网络连通性
//        try (Socket socket = new Socket()) {
//            socket.connect(new InetSocketAddress("admserver.tlct.com.cn", 636), 5000);
//            System.out.println("网络连接正常");
//        } catch (IOException e) {
//            System.err.println("无法连接到AD服务器: " + e.getMessage());
//            return;
//        }

        try (ADLdapConnectorT connector = new ADLdapConnectorT(domain, ldapUrl)) {
            // 连接AD域
            connector.connect(username, password);
            // 在 try 块中添加搜索代码
            SearchControls searchControls = new SearchControls();
            searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            searchControls.setReturningAttributes(new String[]{"cn", "mail", "telephoneNumber"});

            String filter = "(objectClass=person)";
            NamingEnumeration<SearchResult> results = connector.ldapContext.search(baseDn, filter, searchControls);

            while (results.hasMore()) {
                SearchResult result = results.next();
                System.out.println("DN: " + result.getNameInNamespace());

                Attributes attrs = result.getAttributes();
                System.out.println("CN: " + attrs.get("cn").get());
                System.out.println("Mail: " + attrs.get("mail").get());
                System.out.println("----------------------");
            }

        } catch (NamingException e) {
            System.err.println("连接AD域失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void testBasicConnection() {
        String domain = "tlct.com.cn";
        String ldapUrl = "ldaps://admserver.tlct.com.cn:389";
        String username = "TLCT\\adadministrator";
        String password = "yonyou@123";


        // 1. 首先测试网络连通性
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress("admserver.tlct.com.cn", 389), 5000);
            System.out.println("网络连接正常");
        } catch (IOException e) {
            System.err.println("无法连接到AD服务器: " + e.getMessage());
            return;
        }

        // 2. 尝试建立LDAP连接
        Hashtable<String, String> env = new Hashtable<>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, ldapUrl);
        env.put(Context.SECURITY_AUTHENTICATION, "simple");

        // 尝试两种不同的principal格式
        String[] principalFormats = {
                username,                // user@domain.com
                "uid=" + username + ",DC=tlct,DC=com,DC=cn" // 完整DN
        };

        for (String principal : principalFormats) {
            try {
                env.put(Context.SECURITY_PRINCIPAL, principal);
                env.put(Context.SECURITY_CREDENTIALS, password);

                // 添加超时设置
                env.put("com.sun.jndi.ldap.connect.timeout", "30000");
                env.put("com.sun.jndi.ldap.read.timeout", "30000");

                new InitialLdapContext(env, null).close();
                System.out.println("成功连接，使用principal格式: " + principal);
                return;
            } catch (NamingException e) {
                System.err.println("连接失败，principal格式: " + principal);
                e.printStackTrace();
            }
        }
    }

    // 验证客户端与AD服务器时间差
    public static void checkTimeSync() {
        try {
            String adServer = "admserver.tlct.com.cn";
            Process process = Runtime.getRuntime().exec("nettime \\\\" + adServer);
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
            }
        } catch (IOException e) {
            System.err.println("时间同步检查失败: " + e.getMessage());
        }
    }
}


