package nckd.jimin.jyyy.hr.wtc.wtis.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.plugin.support.util.StringUtils;
import kd.bos.exception.KDException;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.schedule.executor.AbstractTask;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jimin.jyyy.hr.wtc.wtis.util.DingTalkSyncUtil;
import nckd.jimin.jyyy.hr.wtc.wtis.util.SyncPunchCardHelper;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Module           :工时假勤云-打卡管理-打卡数据
 * Description      :同步钉钉打卡记录插件
 * @author Tyx
 * @date  2025/5/22
 * 标识 wtis_punchcarddata
 */

public class SyncPunchCardTask extends AbstractTask implements Plugin {

    private static Log logger = LogFactory.getLog(SyncPunchCardTask.class);
    private static String startTime = "";
    private static String endTime = "";
    private static String accessToken = "";
    private static String tokenParamKey = "getTokenUrl";
    private static String punchParamKey = "getPunchUrl";

    private static HRBaseServiceHelper PUNCH_CARD_HELPER = new HRBaseServiceHelper("wtis_punchcarddata");
    /**
     * 获取钉钉打卡数据
     * 钉钉接口限制：50个人，查询时间跨度不能超过半年，查询时间范围不能超过一周
     * @param requestContext
     * @param map
     * @throws KDException
     */
    @Override
    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
        logger.info("开始执行同步钉钉打卡数据：{}", System.currentTimeMillis());
        //初始化时间范围
        try {
            initDateRange(map);
            //获取映射用户信息
            DynamicObjectCollection mappingCols = DingTalkSyncUtil.getMappingInfo();
            //转换为Map, key = openId, value = 人员工号
            Map<String, String> openMap = mappingCols.stream().collect(Collectors.toMap((dyx) -> {
                return dyx.getString("openid");
            }, (dyx) -> {
                return dyx.getString("user.number");
            }));
            List openList = new ArrayList<>(openMap.keySet());
            logger.info("本次需要同步打卡数据人员数量 : {}", openList.size());
            accessToken = DingTalkSyncUtil.getAccessToken();
            logger.info("获取access_token : {}", accessToken);
            if(StringUtils.isEmpty(accessToken)) {
                logger.info("获取钉钉access_token失败");
                DingTalkSyncUtil.createLog(DingTalkSyncUtil.v_error, "获取钉钉access_token失败", "", DingTalkSyncUtil.SyncPunch);
            }
            else {
                String punchUrl = DingTalkSyncUtil.getParamValue(punchParamKey);
                punchUrl = punchUrl + "access_token=" + accessToken;
                logger.info("调用打卡数据同步url : {}" + punchUrl);
                batchDoPost(openList, punchUrl, openMap);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 批量调用Post请求
     * @param openList
     * @return
     */
    public List batchDoPost(List openList, String url, Map openMap) throws IOException {
        int size = 50;   //每批调用人数
        int totalSize = openList.size();    //总人数
        int totalPage = totalSize % size == 0 ? totalSize / size : totalSize / size + 1;
        List responseList = new ArrayList();
        for (int i = 1; i <= totalPage; i++) {
            int startIndex = (i - 1) * size;
            int endIndex = Math.min(startIndex + size, totalSize);
            JSONArray actualArr = new JSONArray();
            for (int m = startIndex; m < endIndex; m++) {
                actualArr.add(openList.get(m));
            }
            JSONObject param = buildContent(actualArr);
            //先批量调用完，然后再批量处理打卡数据
            JSONObject response = DingTalkSyncUtil.doPostByHttpClient(url, param);
            logger.info("分页调用钉钉接口返回信息，第{}页：{}", String.valueOf(i), response);
            if(response.getInteger("errcode") == 0 ) {
                DingTalkSyncUtil.createLog(DingTalkSyncUtil.v_success, param.toJSONString(), response.toJSONString(), DingTalkSyncUtil.SyncPunch);
                SyncPunchCardHelper.savePunchCardData(response.getJSONArray("recordresult"), openMap);
            }
            else {
                logger.info("分页调用钉钉打卡数据接口第{}页出错 : {}" ,String.valueOf(i), response);
                DingTalkSyncUtil.createLog(DingTalkSyncUtil.v_error, param.toJSONString(), response.toJSONString(), DingTalkSyncUtil.SyncPunch);
            }
        }
        return responseList;
    }

    /**
     * 构造参数
     * @param actualArr 人员openID列表
     * @return
     */
    public JSONObject buildContent (JSONArray actualArr) {
        JSONObject ob = new JSONObject();
        ob.put("checkDateFrom", startTime);
        ob.put("checkDateTo", endTime);
        ob.put("isI18n", "false");
        ob.put("userIds", actualArr);
        return ob;
    }

    /**
     * 根据调度作业上配置的参数初始化时间范围
     * @param map
     */
    public void initDateRange(Map<String, Object> map) throws ParseException {
        boolean isAuto = Boolean.valueOf(map.get("isAuto").toString());
        //因为考勤机有离线上传，实际打卡时间可能非当天，这里预留一个补偿机制
        if(!isAuto) {
            startTime = map.get("startTime").toString();
            endTime = map.get("endTime").toString();
        }
        //取当天时间00：00：00 - 23：59：59
        //20250710，改成取前天 00：00：00 - 今天 23：59：59
        else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Calendar startCalendar = Calendar.getInstance();
            startCalendar.add(Calendar.DAY_OF_MONTH, -2);
            startCalendar.set(Calendar.HOUR_OF_DAY, 00);
            startCalendar.set(Calendar.MINUTE, 00);
            startCalendar.set(Calendar.SECOND, 00);
            startTime = sdf.format(startCalendar.getTime());

            Calendar endCalendar = Calendar.getInstance();
            endCalendar.set(Calendar.HOUR_OF_DAY, 23);
            endCalendar.set(Calendar.MINUTE, 59);
            endCalendar.set(Calendar.SECOND, 59);
            endTime = sdf.format(endCalendar.getTime());
        }
    }

}