package nckd.jimin.jyyy.hr.tsrsc.plugin.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.utils.ObjectUtils;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.util.HttpClientUtils;
import nckd.jimin.jyyy.hr.wtc.wtis.util.DingTalkSyncUtil;
import org.apache.commons.net.util.Base64;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.security.cert.CertificateException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

/**
 * Moka工具类
 * @author ：Tyx
 * @since ：2025-05-28
 */
public class MokaApiUtil {
    private static Log logger = LogFactory.getLog(MokaApiUtil.class);
    private static String SCHEME_HTTPS = "https";
    /**
     * 新增招聘需求
     * @param recruitTypeFlag 招聘模式可选值：1：社招  2：校招
     * @param bodyData            请求体
     * @return 返回体
     */
    public static JSONObject addMokaCurrentHire(String recruitTypeFlag, JSONObject bodyData) throws IOException {
        String url = getParamValue("moka_url")
                + "/api-platform/v1/headcount"
                + "?currentHireMode=" + recruitTypeFlag;
        Map<String, String> headers = new HashMap();
        headers.put("Content-Type", "application/json");
        headers.put("Accept", "*/*");
        headers.put("Authorization", "Basic " + Base64.encodeBase64String((getParamValue("moka_apikey") + ":").getBytes()));
        logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        String responseEntify = postjson(url, headers, bodyData.toJSONString(), 10000, 10000);

        logger.info(responseEntify);
        JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
        return result;
    }

    /**
     * 同步人员信息
     * @param url
     * @param bodyData
     * @return
     * @throws IOException
     */
    public static JSONObject syncUserInfo (String url, JSONObject bodyData) throws IOException {
        Map<String, String> headers = new HashMap();
        headers.put("Content-Type", "application/json");
        headers.put("Accept", "*/*");
        headers.put("Authorization", "Basic " + Base64.encodeBase64String((getParamValue("moka_apikey") + ":").getBytes()));
        logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        String responseEntify = postjson(url, headers, bodyData.toJSONString(), 10000, 10000);
        logger.info(responseEntify);
        JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
        return result;
    }

    /**
     * 调用Moka接口
     * @param url
     * @param bodyData
     * @return
     * @throws IOException
     */
    public static JSONObject doPostByHttpClient(String url, JSONObject bodyData) throws IOException {
        Map<String, String> headers = new HashMap();
        headers.put("Content-Type", "application/json");
        headers.put("Accept", "*/*");
        headers.put("Authorization", "Basic " + Base64.encodeBase64String((getParamValue("moka_apikey") + ":").getBytes()));
        logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        String responseEntify = HttpClientUtils.postjson(url, headers, bodyData.toJSONString(), 10000, 10000);

        logger.info(responseEntify);
        JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
        return result;
    }

    public static JSONObject doKingdeePostByHttpClient(String url, JSONObject bodyData) throws IOException {
        Map<String, String> headers = new HashMap();
        headers.put("Content-Type", "application/json");
        headers.put("Accept", "*/*");
        logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
        String responseEntify = HttpClientUtils.postjson(url, headers, bodyData.toJSONString(), 10000, 10000);
        logger.info(responseEntify);
        JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
        return result;
    }

    public static String postjson(String url, Map<String, String> header, String json, int connectionTimeout, int readTimeout) throws IOException {
        String CONTENT_TYPE_TEXT_JSON = "text/json;";
        String data = "";
        HttpClient client = null;
        HttpPost post = new HttpPost(url);
        URI uri = post.getURI();
        if (SCHEME_HTTPS.equals(uri.getScheme())) {
            client = wrapperHttpClient(connectionTimeout, readTimeout);
            if (client == null) {
                return data;
            }
        } else {
            client = createHttpClient(connectionTimeout, readTimeout);
            HttpParams httpParams = client.getParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeout);
            HttpConnectionParams.setSoTimeout(httpParams, readTimeout);
        }

        try {
            if (header != null && header.size() != 0) {
                Iterator<String> iterator = header.keySet().iterator();

                while(iterator.hasNext()) {
                    String key = (String)iterator.next();
                    post.setHeader(key, (String)header.get(key));
                }
            }

            StringEntity se = new StringEntity(json, ContentType.APPLICATION_JSON);
            se.setContentType("text/json;");
            post.setEntity(se);
            HttpResponse response = client.execute(post);
            //Moka调用失败 statusCode = 403
            //if (response.getStatusLine().getStatusCode() == 200) {
            HttpEntity resEntity = response.getEntity();
            Header respHeader = resEntity.getContentEncoding();
            if (respHeader == null || !"gzip".equalsIgnoreCase(respHeader.getValue()) && !"x-gzip".equalsIgnoreCase(respHeader.getValue())) {
                data = EntityUtils.toString(resEntity, "UTF-8");
            } else {
                GzipDecompressingEntity gzipEntity = new GzipDecompressingEntity(resEntity);
                InputStream in = gzipEntity.getContent();
                data = getHTMLContent(in);
            }
            //}
        } catch (IOException var19) {
            logger.warn("Http postjson error", var19);
            throw var19;
        } catch (Exception e){
            logger.warn("Http postjson error", e);
            throw e;
        } finally {
            post.releaseConnection();
        }
        return data;
    }

    private static String getHTMLContent(InputStream in) {
        StringBuffer sb = new StringBuffer();
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        try {
            String line = null;
            while((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException var12) {
            logger.error("getHTMLContent error", var12);
        } finally {
            try {
                br.close();
            } catch (IOException var11) {
                logger.error("getHTMLContent error", var11);
            }
        }
        return sb.toString();
    }

    private static HttpClient createHttpClient(int connectionTimeout, int readTimeout) {
        HttpClient client = new DefaultHttpClient();
        HttpParams httpParams = client.getParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeout);
        HttpConnectionParams.setSoTimeout(httpParams, readTimeout);
        return client;
    }

    public static HttpClient wrapperHttpClient(int connectionTimeout, int readTimeout) {
        try {
            final X509TrustManager trustManager = new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(final javax.security.cert.X509Certificate[] arg0, final String arg1) throws CertificateException {
                }
                public void checkServerTrusted(final javax.security.cert.X509Certificate[] arg0, final String arg1) throws CertificateException {
                }
                @Override
                public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws java.security.cert.CertificateException {
                }
                @Override
                public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws java.security.cert.CertificateException {
                }
            };
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init((KeyManager[])null, new TrustManager[]{trustManager}, (SecureRandom)null);
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
            RequestConfig requestConfig = RequestConfig.custom().setCookieSpec("standard-strict").setConnectTimeout(connectionTimeout).setConnectionRequestTimeout(connectionTimeout).setSocketTimeout(readTimeout).setExpectContinueEnabled(Boolean.TRUE).setTargetPreferredAuthSchemes(Arrays.asList("NTLM", "Digest")).setProxyPreferredAuthSchemes(Arrays.asList("Basic")).build();
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).build();
            return closeableHttpClient;
        } catch (Exception var9) {
            logger.error("包装无证书校验客户端失败:" + var9.getMessage());
            return null;
        }
    }


    /**
     * 新增调用日志
     *
     * @param docNumber 调用单据标识
     * @param docName   调用单据名称
     * @param system    调用系统
     * @param url       调用接口url
     * @param request   请求报文
     * @param response  返回报文
     */
    public static void newApiLog(String docNumber, String docName, String system, String url, String request, String response) {
        DynamicObject apiLog = BusinessDataServiceHelper.newDynamicObject("nckd_mokaapilog");
        // 调用单据标识
        apiLog.set("number", docNumber);
        // 调用单据名称
        apiLog.set("name", docName);
        // 数据状态：已审核
        apiLog.set("status", "C");
        // 调用人
        apiLog.set("creator", RequestContext.get().getCurrUserId());
        // 使用状态：可用
        apiLog.set("enable", "1");
        // 调用接口url
        apiLog.set("nckd_interfaceurl", url);
        // 调用接口时间
        apiLog.set("createtime", new Date());
        if (request.length() < 200) {
            apiLog.set("nckd_request", request);
        } else {
            apiLog.set("nckd_request", request.substring(0, 200) + "...");
        }
        apiLog.set("nckd_request_tag", request);

        if (response.length() < 200) {
            apiLog.set("nckd_response", response);
        } else {
            apiLog.set("nckd_response", response.substring(0, 200) + "...");
        }
        apiLog.set("nckd_response_tag", response);
        SaveServiceHelper.save(new DynamicObject[]{apiLog});
    }

    /**
     * 获取参数值
     * @param key
     * @return
     */
    public static String getParamValue(String key) {
        QFilter filter = new QFilter("number", QCP.equals, "Moka");
        filter.and("nckd_entryentity.nckd_key",QCP.equals, key);
        DynamicObject bill = QueryServiceHelper.queryOne("nckd_commonparams", "nckd_entryentity.nckd_value", new QFilter[]{filter});
        return bill.getString("nckd_entryentity.nckd_value");
    }

    /**
     * 获取参数值，没找到返回默认值
     * @param key
     * @param def
     * @return
     */
    public static String getParamValue(String key, String def) {
        QFilter filter = new QFilter("number", QCP.equals, "Moka");
        filter.and("nckd_entryentity.nckd_key",QCP.equals, key);
        DynamicObject bill = QueryServiceHelper.queryOne("nckd_commonparams", "nckd_entryentity.nckd_value", new QFilter[]{filter});
        if(ObjectUtils.isEmpty(bill)) {
            return def;
        }
        else {
            return bill.getString("nckd_entryentity.nckd_value");
        }
    }

    /**
     * 按分钟漂移
     * @param offset
     * @return
     */
    public static LocalDateTime offsetMinute(int offset) {
        LocalDateTime now = LocalDateTime.now();
        Duration fiveMinutes = Duration.ofMinutes(offset);
        LocalDateTime fiveMinutesAgo = now.minus(fiveMinutes);
        return fiveMinutesAgo;
    }


}
