package com.kingdee.eas.custom.synctask;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.IObjectPK;
import com.kingdee.bos.metadata.entity.EntityViewInfo;
import com.kingdee.bos.metadata.entity.FilterInfo;
import com.kingdee.bos.metadata.entity.FilterItemInfo;
import com.kingdee.bos.metadata.entity.SelectorItemInfo;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.eas.base.permission.UserInfo;
import com.kingdee.eas.basedata.person.IPerson;
import com.kingdee.eas.basedata.person.PersonCollection;
import com.kingdee.eas.basedata.person.PersonFactory;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.log.ISyncLog;
import com.kingdee.eas.custom.log.SyncLogFactory;
import com.kingdee.eas.custom.log.SyncLogInfo;
import com.kingdee.eas.custom.log.app.DataDirectionEnum;
import com.kingdee.eas.custom.log.app.DockingSystemEnum;
import com.kingdee.eas.custom.log.app.SyncEntityNameEnum;
import com.kingdee.eas.custom.log.app.SyncStatusEnum;
import com.kingdee.eas.custom.synctask.utils.HRTimeWebUtils;
import com.kingdee.eas.framework.CoreBaseCollection;
import com.kingdee.eas.hr.ats.*;
import com.kingdee.eas.utils.EncryptUtils;
import com.kingdee.eas.utils.ExpiringMapCache;
import com.kingdee.util.StringUtils;
import okhttp3.*;
import org.apache.log4j.Logger;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.sql.Connection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Date;

public class SyncTranForMJFacadeControllerBean extends AbstractSyncTranForMJFacadeControllerBean {
    private static Logger logger = Logger.getLogger(SyncTranForMJFacadeControllerBean.class);
    private Properties propt = new Properties();
    private static ExpiringMapCache<String, String> cache = new ExpiringMapCache();
    private long durationInMillis = 84600000;
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public SyncTranForMJFacadeControllerBean() throws BOSException {
        String syncOAConfigPath = System.getProperty("EAS_HOME") + "/server/properties/scy/syncMJConfig.properties";
        try {
            propt.load(new FileInputStream(syncOAConfigPath));
        } catch (IOException e) {
            e.printStackTrace();
            String errorMsg = "获取配置文件报错，请检查配置：" + syncOAConfigPath + "   " + e.getMessage();
            throw new BOSException(errorMsg);
        }
    }


    /**
     * 同步门禁打卡记录
     *
     * @param ctx
     * @param startDate
     * @param endDate
     * @throws BOSException
     */
    @Override
    protected void _syncAccessRecord(Context ctx, String startDate, String endDate) throws BOSException {
        logger.error("_syncAccessRecord------");
        JSONArray jsonArray = new JSONArray();
        Properties properties = new Properties();
        properties.put("version", propt.getProperty("version"));
        properties.put("tenantCode", propt.getProperty("tenantCode"));//租户编号，平台提供
        properties.put("language", propt.getProperty("language"));//语言
        properties.put("tenantSecret", propt.getProperty("tenantSecret"));//密钥
        properties.put("account", propt.getProperty("account"));//接口账号
        properties.put("password", propt.getProperty("passwordMj"));//接口账号密码
        properties.put("getTokenPath", propt.getProperty("getTokenPath"));//获取token接口地址
        int pageIndex = 1;
        try {
            while (true) {
                // 获取前三天的时间
                JSONObject params = buildRequestParams(pageIndex, startDate, endDate);
                String payload = params.toJSONString();
                Map<String, String> headers = getHeader(payload, false);

                OkHttpClient client = new OkHttpClient.Builder().build();
                MediaType mediaType = MediaType.parse("application/json");
                RequestBody body = RequestBody.create(mediaType, payload);
                Request.Builder requestBuilder = new Request.Builder()
                        .url(propt.getProperty("getMJPath"))
                        .method("POST", body)
                        .addHeader("Content-Type", "application/json");
                // 批量添加请求头
                for (Map.Entry<String, String> header : headers.entrySet()) {
                    requestBuilder.header(header.getKey(), header.getValue());
                }
                Response response = client.newCall(requestBuilder.build()).execute();
                logger.error("response----" + response.isSuccessful());
                if (response.isSuccessful()) {
                    //重置token,每次调用接口后刷新token
                    resetToken();
                    String resultBody = response.body().string();
                    logger.error("resultBody----" + resultBody);
                    JSONObject result = JSONObject.parseObject(resultBody);
                    logger.error("respMap----" + result);

                    if (result.get("code").equals("0") || Integer.parseInt(result.get("code").toString()) == 0) {
                        JSONArray data = result.getJSONArray("data");
                        int pageCount = result.getInteger("pageCount");
                        jsonArray.add(data);
                        if (pageIndex >= pageCount) {
                            break;
                        }
                        pageIndex++;

                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BOSException(e.getMessage());
        }

        for (int i = 0; i < jsonArray.size(); i++) {
            JSONArray resultData = jsonArray.getJSONArray(i);

            //保存门禁打卡记录
            saveMJPunchCardData(ctx, resultData);
        }
    }

    /**
     * 日期格式装换
     *
     * @param date
     */
    private String dateFormatConversion(String date) {
        // 定义输入日期时间字符串的格式
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 解析输入的字符串为 LocalDateTime 对象
        LocalDateTime localDateTime = LocalDateTime.parse(date, inputFormatter);
        // 将 LocalDateTime 对象转换为 OffsetDateTime 对象，并指定时区偏移为 +08:00
        OffsetDateTime offsetDateTime = localDateTime.atOffset(ZoneOffset.of("+08:00"));
        // 定义输出的日期时间格式，即 ISO 8601 格式
        DateTimeFormatter outputFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
        // 将 OffsetDateTime 对象格式化为目标字符串
        String outputDateStr = offsetDateTime.format(outputFormatter);
        return outputDateStr;
    }

    /**
     * 获取前三天的时间
     *
     * @param startDate
     * @return
     * @throws ParseException
     */
    private JSONObject buildRequestParams(int pageIndex, String startDate, String endDate) {
        JSONObject params = new JSONObject();
        params.put("pageIndex", pageIndex);
        params.put("pageSize", propt.getProperty("pageSize"));
        params.put("eventResult", 1);
        String array = propt.getProperty("array");
        String array2 = propt.getProperty("array2");
        Set<String> set = AtsUtil.toSet(array + array2);
        params.put("pointCodes", set);//门点编号
        // 获取当前时间，并设置为 UTC+8 时区
        ZonedDateTime now = ZonedDateTime.now(ZoneOffset.ofHours(8));
        // 获取前两天的日期时间
        ZonedDateTime twoDaysAgo = now.minusDays(2);
        ZonedDateTime plusDays = now.plusDays(1);
        // 定义目标格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
        // 格式化时间 当前时间前两天
        String formattedTime = twoDaysAgo.format(formatter);
        String plusDaysTime = plusDays.format(formatter);
        // 输出结果
        if (!StringUtils.isEmpty(startDate) && !StringUtils.isEmpty(endDate)) {
            params.put("minEventTime", dateFormatConversion(startDate));
            params.put("maxEventTime", dateFormatConversion(endDate));
        } else {
            params.put("minEventTime", formattedTime);
            params.put("maxEventTime", plusDaysTime);
        }
        return params;
    }


    /**
     * 保存门禁打卡记录
     *
     * @param ctx
     * @param jsonArray
     */
    public void saveMJPunchCardData(Context ctx, JSONArray jsonArray) {
        logger.error("saveMJPunchCardData----");
        try {
            int success = 0;
            int error = 0;
            Set<String> setCardId = new HashSet();
            Set<String> EquNoSet = new HashSet();
            Timestamp minDateTime = null;
            Timestamp maxDateTime = null;
            CoreBaseCollection cardCollFinally = new CoreBaseCollection();
            CoreBaseCollection cardColl = new CoreBaseCollection();
            JSONArray formatErrorRecords = new JSONArray();
            //存储相同的数据
            JSONArray duplicateRecords = new JSONArray();
            //存储考勤日期为空的数据
            JSONArray notExistRecords = new JSONArray();
            JSONArray seccussArray = new JSONArray();
            //获取员工编码
            IPerson iPerson = PersonFactory.getLocalInstance(ctx);
            PersonCollection personCollection = iPerson.getPersonCollection("select number ");
            Set set = new HashSet();
            for (int i = 0; i < personCollection.size(); i++) {
                PersonInfo personInfo = personCollection.get(i);
                set.add(personInfo.getNumber().toString());
            }
            for (int j = 0; j < jsonArray.size(); j++) {
                JSONObject resultData = jsonArray.getJSONObject(j);
                ++success;
                String personNumber = resultData.getString("empCode");//员工编码
                String punchCardDate = resultData.getString("eventTime"); //打卡时间
                //String punchCardDate = resultData.getString("checkTime"); //打卡时间
                String RecDate = punchCardDate.substring(0, 10);// 考勤日期
                String RecTime = punchCardDate.substring(11, 19);// 考勤时间
                //String locationDetail = resultSet.getString("name"); //打卡地点
                //String EquNo = resultSet.getString("EquNo"); //考勤机编码
                //String exceptionType = resultSet.getString("EquNo"); // 打卡/异常类型
                //Date punchDate = HRTimeWebUtils.stringToShortDate(RecDate, true);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
                SimpleDateFormat sdfymd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = sdf.parse(punchCardDate);
                String format = sdfymd.format(date);
                Date punchDate = com.kingdee.eas.custom.synctask.utils.HRTimeWebUtils.stringToShortDate(RecDate, true);
                Timestamp punchCardTime = com.kingdee.eas.custom.synctask.utils.HRTimeWebUtils.stringToTimestamp(format, true);
                // 处理数据
                if (punchCardDate != null && punchCardTime != null) {
                    PunchCardRecordInfo cardInfo = new PunchCardRecordInfo();
                    //考勤机编码
                    cardInfo.setEquipmentNum("001");
                    //考勤编码
                    cardInfo.setAttendanceNum(personNumber);
                    //打卡日期
                    cardInfo.setPunchCardDate(punchDate);
                    //打卡时间
                    cardInfo.setPunchCardTime(punchCardTime);
                    // 打卡来源
                    cardInfo.setPunchCardSource(PunchCardSourceEnum.attenceMachine);
                    // 打卡位置
                    cardInfo.setPunchCardPlace((String) resultData.get("pointName"));
                    // 有效
                    PunchCardStateEnum punchCardStateEnum;
                    //if ((boolean) resultData.get("isActive")) {
                    //    punchCardStateEnum = PunchCardStateEnum.normal;
                    //} else {
                    //    punchCardStateEnum = PunchCardStateEnum.cancelled;
                    //}
                    punchCardStateEnum = PunchCardStateEnum.normal;
                    cardInfo.setPunchCardState(punchCardStateEnum);
                    ////简称
                    //cardInfo.setSimpleName(exceptionType);
                    //描述
                    cardInfo.setDescription("门禁打卡机");
                    EquNoSet.add("001");
                    if (!StringUtils.isEmpty(personNumber)) {
                        if (!set.contains(personNumber)) {
                            continue;
                        }
                        setCardId.add(personNumber);
                        cardColl.add(cardInfo);
                    }

                    if (minDateTime != null && maxDateTime != null) {
                        if (punchCardTime.getTime() < minDateTime.getTime()) {
                            minDateTime = punchCardTime;
                        } else if (punchCardTime.getTime() > maxDateTime.getTime()) {
                            maxDateTime = punchCardTime;
                        }
                    } else {
                        minDateTime = punchCardTime;
                        maxDateTime = punchCardTime;
                    }

                } else {
                    formatErrorRecords.add(resultData);
                }
            }
            // 考勤档案
            Map<String, AttendanceFileInfo> attendanceFileMap = AttendanceFileFactory.getLocalInstance(ctx).getPersonByAttendanceNum(setCardId);
            logger.error("attendanceFileMap-----" + attendanceFileMap);
            logger.error("setCardId-----" + setCardId);
            //相同的数据
            PunchCardRecordCollection existColl = this.getExistedPunchCardRecordCollection(ctx, minDateTime, maxDateTime, setCardId);
            logger.error("existColl-----" + existColl.size());
            for (int i = 0; i < cardColl.size(); ++i) {
                Map map = new HashMap();
                // 原始打卡记录实体
                PunchCardRecordInfo cardInfo = (PunchCardRecordInfo) cardColl.get(i);
                JSONObject jsObject = new JSONObject();
                jsObject.put("deviceid", cardInfo.getEquipmentNum()); // deviceid --EquNo
                jsObject.put("userid", cardInfo.getAttendanceNum()); // userid --CardId
                jsObject.put("RecDate", com.kingdee.eas.custom.synctask.utils.HRTimeWebUtils.dateShortToString(cardInfo.getPunchCardDate())); //checkin_time --RecDate
                jsObject.put("RecTime", com.kingdee.eas.custom.synctask.utils.HRTimeWebUtils.timestampToString(cardInfo.getPunchCardTime()).substring(11)); //checkin_time --RecDate
                map.put("userid", cardInfo.getAttendanceNum());
                map.put("RecDate", com.kingdee.eas.custom.synctask.utils.HRTimeWebUtils.dateShortToString(cardInfo.getPunchCardDate()));
                map.put("RecTime", HRTimeWebUtils.timestampToString(cardInfo.getPunchCardTime()).substring(11));
                //员工是否有考勤档案
                if (attendanceFileMap.containsKey(cardInfo.getAttendanceNum())) {
                    if (existColl.contains(cardInfo)) {
                        duplicateRecords.add(jsObject);
                    } else {
                        // 打卡位置 ，考勤机 的地址
                        cardInfo.setPunchCardPlace(cardInfo.getPunchCardPlace());
                        //打卡来源
                        cardInfo.setPunchCardSource(PunchCardSourceEnum.attenceMachine);
                        // 考勤实体
                        AttendanceFileInfo attendanceFileInfo = (AttendanceFileInfo) attendanceFileMap.get(cardInfo.getAttendanceNum());
                        // 姓名
                        cardInfo.setProposer(attendanceFileInfo.getProposer());
                        // HR 组织
                        cardInfo.setHrOrgUnit(attendanceFileInfo.getHrOrgUnit());
                        //行政组织
                        cardInfo.setAdminOrgUnit(attendanceFileInfo.getAdminOrgUnit());
                        cardInfo.setCreator((UserInfo) ctx.get("UserInfo"));
                        cardInfo.setLastUpdateUser((UserInfo) ctx.get("UserInfo"));
                        cardInfo.setCreateTime(new Timestamp((new Date()).getTime()));
                        cardInfo.setLastUpdateTime(new Timestamp((new Date()).getTime()));
                        cardCollFinally.add(cardInfo);
                    }
                    seccussArray.add(map);
                } else {
                    ++error;
                    notExistRecords.add(jsObject);
                }
            }
            logger.error("cardCollFinally-----" + cardCollFinally.size());
            logger.error("success-----" + success);
            logger.error("error-----" + error);
            logger.error("notExistRecords--list---" + notExistRecords);
            logger.error("notExistRecords-----" + notExistRecords.size());
            logger.error("seccussArray--Size-----" + seccussArray.size());
            logger.error("seccussArray-----" + seccussArray);
            if(cardCollFinally.size()>=0){
            IObjectPK[] iObjectPKS = PunchCardRecordFactory.getLocalInstance(ctx).saveBatchData(cardCollFinally);
                logger.error("iObjectPKS----" + iObjectPKS.length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 重置token,每次调用接口后刷新token
     */
    private void resetToken() {
        String token = cache.get("token");
        if (org.apache.commons.lang3.StringUtils.isBlank(token)) {
            getTokenByRemote();
        } else {
            cache.put("token", token, durationInMillis);//23.5小时
        }
    }

    /**
     * 获取请求头
     *
     * @param payload    body的json字符串
     * @param isGetToken 是否获取token请求
     * @return
     */
    private Map<String, String> getHeader(String payload, boolean isGetToken) {
        Map<String, String> signParams = new HashMap<>();
        signParams.put("version", propt.getProperty("version"));
        signParams.put("transId", UUID.randomUUID().toString());
        signParams.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
        signParams.put("tenantCode", propt.getProperty("tenantCode"));//租户编号，平台提供
        signParams.put("language", propt.getProperty("language"));//语言支持
        if (!isGetToken) {
            signParams.put("token", getToken());
        }
        signParams.put("payload", payload);//发起请求时 body 的 json 字符串
        //密钥必须放在生成签名代码之前
        signParams.put("tenantSecret", propt.getProperty("tenantSecret"));
        signParams.put("sign", createSign(signParams));
        return signParams;
    }

    /**
     * 获取token
     *
     * @return
     */
    private String getToken() {
        String token = cache.get("token");
        if (org.apache.commons.lang3.StringUtils.isBlank(token)) {
            token = getTokenByRemote();
        }
        return token;
    }

    /**
     * 远程获取token
     *
     * @return
     */
    private String getTokenByRemote() {
        try {
            com.alibaba.fastjson.JSONObject params = new com.alibaba.fastjson.JSONObject();
            params.put("account", propt.getProperty("account"));
            String password = propt.getProperty("passwordMj");
            params.put("password", EncryptUtils.sha256(password, false));
            String payload = params.toJSONString();
            String getTokenPath = propt.getProperty("getTokenPath");

            Map<String, String> headers = getHeader(payload, true);
            OkHttpClient client = new OkHttpClient.Builder().build();
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, payload);
            Request.Builder requestBuilder = new Request.Builder()
                    .url(getTokenPath)
                    .method("POST", body)
                    .addHeader("Content-Type", "application/json");
            // 批量添加请求头
            for (Map.Entry<String, String> header : headers.entrySet()) {
                requestBuilder.header(header.getKey(), header.getValue());
            }
            Response response = client.newCall(requestBuilder.build()).execute();
            ObjectMapper mapper = new ObjectMapper();
            if (response.isSuccessful()) {
                Map<String, Object> result = mapper.readValue(response.body().string(), Map.class);
                if ("success".equals(result.get("msg"))) {
                    String token = (String) result.get("data");
                    cache.put("token", token, 84600000);//23.5小时
                    return token;
                } else {
                    throw new RuntimeException("远程获取token报错: ");
                }
            } else {
                throw new RuntimeException("远程获取token报错: ");
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("远程获取token报错: " + e.getMessage());
        }
    }

    /**
     * 生成签名
     *
     * @param signParams 参与签名的参数
     * @return
     */
    private String createSign(Map<String, String> signParams) {
        String tenantSecret = signParams.get("tenantSecret");
        signParams.remove("tenantSecret");
        String linkStr = createLinkStr(signParams, "&");
        linkStr = linkStr + "&tenantSecret=" + tenantSecret;
        return EncryptUtils.sha256(linkStr, true);
    }

    /**
     * 创建链接字符串
     *
     * @param params  参数
     * @param linkStr 连接字符
     * @return
     */
    private static String createLinkStr(Map<String, String> params, String linkStr) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {
                content.append(key).append("=").append(value);
            } else {
                content.append(key).append("=").append(value).append(linkStr);
            }
        }
        return content.toString();
    }

    /**
     * 打卡记录同步
     *
     * @param ctx
     * @param beginDate
     * @param endDate
     * @throws BOSException
     */
    @Override
    protected void _syncPunchRecordFromMJ(Context ctx, String beginDate, String endDate) throws BOSException {
        String url = propt.getProperty("jdbc");
        String username = propt.getProperty("user");
        String password = propt.getProperty("password");
        ISyncLog iSyncLog = SyncLogFactory.getLocalInstance(ctx);
        SyncLogInfo syncLogInfo = new SyncLogInfo();
        syncLogInfo.setEntityName(SyncEntityNameEnum.cardRecord);
        syncLogInfo.setDataDirection(DataDirectionEnum.flowInto);
        syncLogInfo.setDockingSystem(DockingSystemEnum.accessControl);
        int success = 0;
        int error = 0;
        try {
            // 加载SQL Server JDBC驱动程序
            //Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            // 建立连接
            Connection connection = DriverManager.getConnection(url, username, password);
            // 创建Statement对象
            Statement statement = connection.createStatement();
            String oneMOnthDate = null;
            String nowDate = null;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            //获取当前时间以及一个月前的时间
            if (StringUtils.isEmpty(beginDate) && StringUtils.isEmpty(endDate)) {
                // 获取当前日期
                Date now = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(now);
                // 将月份减1（这里只是简单的月份减1，没有考虑日期边界等复杂情况）
                calendar.add(Calendar.MONTH, -1);
                Date one_month_ago = calendar.getTime();
                oneMOnthDate = sdf.format(one_month_ago);
                nowDate = sdf.format(now);
                logger.error("PunchCardRecordEx----oneMOnthDate--" + oneMOnthDate);
                logger.error("PunchCardRecordEx----nowDate--" + nowDate);
            } else {
                oneMOnthDate = beginDate;
                nowDate = endDate;
            }
            // 执行查询语句
            String query = "select \n" +
                    "userinfo.SSN as personNumber ,\n" +
                    "checkin.CHECKTIME as checkTime\n" +
                    "from  checkinout as checkin\n" +
                    "left join USERINFO as userinfo on userinfo.USERID = checkin.USERID\n" +
                    "where checkin.CHECKTIME >='" + oneMOnthDate + "' and checkin.CHECKTIME <='" + nowDate + "'\n";
            //String query = "\n" +
            //        " \n" +
            //        "select \n" +
            //        "userinfo.SSN as personNumber ,\n" +
            //        "checkin.CHECKTIME as checkTime\n" +
            //        "from  checkinout as checkin\n" +
            //        "left join USERINFO as userinfo on userinfo.USERID = checkin.USERID\n" +
            //        "where checkin.CHECKTIME >='2024-10-29' and checkin.CHECKTIME <='2024-10-30'\n" +
            //        " ";
            ResultSet resultSet = statement.executeQuery(query);
            Set<String> setCardId = new HashSet();
            Set<String> EquNoSet = new HashSet();
            Timestamp minDateTime = null;
            Timestamp maxDateTime = null;
            CoreBaseCollection cardCollFinally = new CoreBaseCollection();
            CoreBaseCollection cardColl = new CoreBaseCollection();
            JSONArray formatErrorRecords = new JSONArray();
            //存储相同的数据
            JSONArray duplicateRecords = new JSONArray();
            //存储考勤日期为空的数据
            JSONArray notExistRecords = new JSONArray();

            JSONArray seccussArray = new JSONArray();

            // 处理查询结果
            while (resultSet.next()) {
                ++success;
                String personNumber = resultSet.getString("personNumber");//员工编码
                String punchCardDate = resultSet.getString("checkTime"); //打卡时间
                String RecDate = punchCardDate.substring(0, 10);// 考勤日期
                String RecTime = punchCardDate.substring(11, 19);// 考勤时间
                //String locationDetail = resultSet.getString("name"); //打卡地点
                //String EquNo = resultSet.getString("EquNo"); //考勤机编码
                //String exceptionType = resultSet.getString("EquNo"); // 打卡/异常类型
                //Date punchDate = HRTimeWebUtils.stringToShortDate(RecDate, true);
                Date punchDate = HRTimeWebUtils.stringToShortDate(RecDate, true);
                Timestamp punchCardTime = HRTimeWebUtils.stringToTimestamp(punchCardDate, true);
                // 处理数据
                if (punchCardDate != null && punchCardTime != null) {
                    PunchCardRecordInfo cardInfo = new PunchCardRecordInfo();
                    //考勤机编码
                    cardInfo.setEquipmentNum("001");
                    //考勤编码
                    cardInfo.setAttendanceNum(personNumber);
                    //打卡日期
                    cardInfo.setPunchCardDate(punchDate);
                    //打卡时间
                    cardInfo.setPunchCardTime(punchCardTime);
                    // 打卡来源
                    cardInfo.setPunchCardSource(PunchCardSourceEnum.dbsynch);
                    // 打卡位置
                    cardInfo.setPunchCardPlace("考勤机打卡");
                    // 有效
                    cardInfo.setPunchCardState(PunchCardStateEnum.normal);
                    ////简称
                    //cardInfo.setSimpleName(exceptionType);
                    //描述
                    cardInfo.setDescription("数据库数据");

                    EquNoSet.add("001");
                    if (!StringUtils.isEmpty(personNumber)) {
                        setCardId.add(personNumber);
                        cardColl.add(cardInfo);
                    }

                    if (minDateTime != null && maxDateTime != null) {
                        if (punchCardTime.getTime() < minDateTime.getTime()) {
                            minDateTime = punchCardTime;
                        } else if (punchCardTime.getTime() > maxDateTime.getTime()) {
                            maxDateTime = punchCardTime;
                        }
                    } else {
                        minDateTime = punchCardTime;
                        maxDateTime = punchCardTime;
                    }

                } else {
                    formatErrorRecords.add(resultSet);
                }
            }
            // 考勤档案
            Map<String, AttendanceFileInfo> attendanceFileMap = AttendanceFileFactory.getLocalInstance(ctx).getPersonByAttendanceNum(setCardId);
            logger.error("attendanceFileMap-----" + attendanceFileMap);
            //相同的数据
            PunchCardRecordCollection existColl = this.getExistedPunchCardRecordCollection(ctx, minDateTime, maxDateTime, setCardId);
            logger.error("existColl-----" + existColl.size());
            for (int i = 0; i < cardColl.size(); ++i) {
                Map map = new HashMap();
                // 原始打卡记录实体
                PunchCardRecordInfo cardInfo = (PunchCardRecordInfo) cardColl.get(i);
                JSONObject jsObject = new JSONObject();
                jsObject.put("deviceid", cardInfo.getEquipmentNum()); // deviceid --EquNo
                jsObject.put("userid", cardInfo.getAttendanceNum()); // userid --CardId
                jsObject.put("RecDate", HRTimeWebUtils.dateShortToString(cardInfo.getPunchCardDate())); //checkin_time --RecDate
                jsObject.put("RecTime", HRTimeWebUtils.timestampToString(cardInfo.getPunchCardTime()).substring(11)); //checkin_time --RecDate
                map.put("userid", cardInfo.getAttendanceNum());
                map.put("RecDate", HRTimeWebUtils.dateShortToString(cardInfo.getPunchCardDate()));
                map.put("RecTime", HRTimeWebUtils.timestampToString(cardInfo.getPunchCardTime()).substring(11));
                //员工是否有考勤档案
                if (attendanceFileMap.containsKey(cardInfo.getAttendanceNum())) {
                    if (existColl.contains(cardInfo)) {
                        duplicateRecords.add(jsObject);
                    } else {
                        // 打卡位置 ，考勤机 的地址
                        cardInfo.setPunchCardPlace(cardInfo.getPunchCardPlace());
                        //打卡来源
                        cardInfo.setPunchCardSource(PunchCardSourceEnum.mobileRegistration);
                        // 考勤实体
                        AttendanceFileInfo attendanceFileInfo = (AttendanceFileInfo) attendanceFileMap.get(cardInfo.getAttendanceNum());
                        // 姓名
                        cardInfo.setProposer(attendanceFileInfo.getProposer());
                        // HR 组织
                        cardInfo.setHrOrgUnit(attendanceFileInfo.getHrOrgUnit());
                        //行政组织
                        cardInfo.setAdminOrgUnit(attendanceFileInfo.getAdminOrgUnit());
                        cardInfo.setCreator((UserInfo) ctx.get("UserInfo"));
                        cardInfo.setLastUpdateUser((UserInfo) ctx.get("UserInfo"));
                        cardInfo.setCreateTime(new Timestamp((new Date()).getTime()));
                        cardInfo.setLastUpdateTime(new Timestamp((new Date()).getTime()));
                        cardCollFinally.add(cardInfo);
                    }
                    seccussArray.add(map);
                } else {
                    ++error;
                    notExistRecords.add(jsObject);
                }
            }
            logger.error("cardCollFinally-----" + cardCollFinally.size());
            logger.error("success-----" + success);
            logger.error("error-----" + error);
            logger.error("notExistRecords--list---" + notExistRecords);
            logger.error("notExistRecords-----" + notExistRecords.size());
            logger.error("seccussArray--Size-----" + seccussArray.size());
            logger.error("seccussArray-----" + seccussArray);
            IObjectPK[] iObjectPKS = PunchCardRecordFactory.getLocalInstance(ctx).saveBatchData(cardCollFinally);
            if (iObjectPKS.length > 0) {
                logger.error("iObjectPKS----" + iObjectPKS.length);
                syncLogInfo.setSyncStatus(SyncStatusEnum.SUCCESS);
                syncLogInfo.setSyncResult(iObjectPKS.toString());
                syncLogInfo.setSyncCount(success);
                syncLogInfo.setSuccessNum(cardCollFinally.size());
                syncLogInfo.setFailNum(error);
                iSyncLog.save(syncLogInfo);
            }
            // 关闭连接
            resultSet.close();
            statement.close();
            connection.close();

        } catch (Exception e) {
            syncLogInfo.setSyncStatus(SyncStatusEnum.ERROR);
            syncLogInfo.setSyncResult(e.getMessage());
            try {
                iSyncLog.save(syncLogInfo);
            } catch (EASBizException ex) {
                throw new RuntimeException(ex);
            }
            e.printStackTrace();
        }
    }


    private PunchCardRecordCollection getExistedPunchCardRecordCollection(Context ctx, Timestamp minDateTime, Timestamp maxDateTime, Set<String> setCardId) throws BOSException {
        EntityViewInfo evi = new EntityViewInfo();
        FilterInfo fi = new FilterInfo();
        evi.setFilter(fi);
        evi.getSelector().add(new SelectorItemInfo("punchCardDate"));
        evi.getSelector().add(new SelectorItemInfo("punchCardTime"));
        evi.getSelector().add(new SelectorItemInfo("punchCardSource"));
        evi.getSelector().add(new SelectorItemInfo("equipmentNum"));
        evi.getSelector().add(new SelectorItemInfo("attendanceNum"));
        fi.getFilterItems().add(new FilterItemInfo("attendanceNum", setCardId, CompareType.INCLUDE));
        fi.getFilterItems().add(new FilterItemInfo("punchCardTime", maxDateTime, CompareType.LESS_EQUALS));
        fi.getFilterItems().add(new FilterItemInfo("punchCardTime", minDateTime, CompareType.GREATER_EQUALS));
        PunchCardRecordCollection existColl = PunchCardRecordFactory.getLocalInstance(ctx).getPunchCardRecordCollection(evi);
        return existColl;

    }
}
