package com.kingdee.eas.custom.attendanceexception.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
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.custom.attendanceexception.*;
import com.kingdee.eas.custom.attendanceexception.bean.DingMsgBean;
import com.kingdee.eas.custom.attendanceexception.bean.SyncAttendanceDataBean;
import com.kingdee.eas.custom.attendanceexception.bizEnum.PushTypeEnum;
import com.kingdee.eas.fi.arap.util.DBUtil;
import com.kingdee.eas.hr.ats.util.AtsDateUtils;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.util.DateTimeUtils;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import com.kingdee.bos.*;
import com.kingdee.eas.common.EASBizException;

import java.io.IOException;
import java.lang.String;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;

public class AttendanceExceptionFacadeControllerBean extends AbstractAttendanceExceptionFacadeControllerBean {
    private static Logger logger =
            Logger.getLogger(AttendanceExceptionFacadeControllerBean.class);
    //通知员工个人消息模板
    private static final String NOTIFYEMPLOYEEMSGTEMPLATE = "您在{0}出现考勤异常！";
    //通知员工个人消息标题
    private static final String NOTIFYEMPLOYEEMSGTitle = "【考勤异常提醒】";
    //通知员工个人消息模板
    private static final String NOTIFYEMPLOYEECUMULATIVEMSGTEMPLATE = "您在{0}考勤异常次数以达到{1}次，请您注意本月考勤！";
    //通知员工个人消息标题
    private static final String NOTIFYEMPLOYEECUMULATIVEMSGTitle = "【员工考勤提醒】";
    //通知员工个人消息模板
//    private static final String NOTIFYEMPLOYEECUMULATIVEMSGTEMPLATE = "您在{0}考勤异常次数以达到{1}次，请您注意本月考勤！";
//    //通知员工个人消息标题
//    private static final String NOTIFYEMPLOYEECUMULATIVEMSGTitle = "【员工考勤提醒】";

    /**
     * 员工个人异常提醒
     *
     * @param ctx
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _notifyEmployeeException(Context ctx) throws BOSException, EASBizException {
        long startTime = System.currentTimeMillis();
        if (logger.isInfoEnabled()) {
            logger.info("AttendanceExceptionFacadeControllerBean.notifyEmployeeException start");
        }
        super._notifyEmployeeException(ctx);
        //1.查询异常数据
        //昨天
        Date preDay = AtsDateUtils.getPreDay(new Date());
        //getAttendanceExceptionData(ctx, preDay, preDay);
        //2.调用接口给对应员工发送异常预警消息


        String msgId = UUID.randomUUID().toString();
        String content = MessageFormat.format(NOTIFYEMPLOYEEMSGTEMPLATE, msgId);
        DingMsgBean dingMsgBean = new DingMsgBean(msgId, NOTIFYEMPLOYEEMSGTitle, content, "");


        //3.保存消息记录
        if (logger.isInfoEnabled()) {
            long endTime = System.currentTimeMillis();
            float duration = (endTime - startTime) / 1000f;
            logger.info(String.format("AttendanceExceptionFacadeControllerBean.notifyEmployeeException end, duration: %fS", duration));
        }
    }

    /**
     * @param ctx
     * @param exceptionLimit 异常次数上限
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _notifyEmployeeCumulativeException(
            Context ctx,
            String exceptionLimit
    ) throws BOSException, EASBizException {
        long startTime = System.currentTimeMillis();
        if (logger.isInfoEnabled()) {
            logger.info("AttendanceExceptionFacadeControllerBean.notifyEmployeeCumulativeException start");
        }
        super._notifyEmployeeCumulativeException(ctx, exceptionLimit);
        int limit = 5;
        if (StringUtils.isNotBlank(exceptionLimit)) {
            limit = Integer.parseInt(exceptionLimit);
        }
        IAttendanceExceptionLog iAttendanceExceptionLog = AttendanceExceptionLogFactory.getLocalInstance(ctx);
        AttendanceExceptionLogInfo logInfo = new AttendanceExceptionLogInfo();
        //推送类型为员工累计异常提醒
        logInfo.setPushType(PushTypeEnum.EMPLOYEEEXCEPTIONALERT);
        String msgId = UUID.randomUUID().toString();
        logInfo.setMessageId(msgId);
        //1.查询异常数据
        Date today = new Date();
        //当前月第一天
        Date currentFirstDay = AtsDateUtils.getCurrentFirstDay(today);
        //昨天
        Date preDay = AtsDateUtils.getPreDay(today);
        //getAttendanceExceptionData(ctx, currentFirstDay, preDay);
        String yearMonth = DateTimeUtils.format(today, "yyyy年M月");
        String content = MessageFormat.format(NOTIFYEMPLOYEECUMULATIVEMSGTEMPLATE, yearMonth, limit);

        //2.调用接口给对应员工发送异常预警消息
        DingMsgBean dingMsgBean = new DingMsgBean(msgId, NOTIFYEMPLOYEECUMULATIVEMSGTitle, content, "");

        //3.保存消息记录

//        attendanceExceptionLogInfo.setMessageResponse("");
//        attendanceExceptionLogInfo.setMessageRequest("");


        if (logger.isInfoEnabled()) {
            long endTime = System.currentTimeMillis();
            float duration = (endTime - startTime) / 1000f;
            logger.info(String.format("AttendanceExceptionFacadeControllerBean.notifyEmployeeCumulativeException end, duration: %fS", duration));
        }
    }

    @Override
    protected void _alertLeaderExceptionTotal(Context ctx) throws BOSException, EASBizException {
        long startTime = System.currentTimeMillis();
        if (logger.isInfoEnabled()) {
            logger.info("AttendanceExceptionFacadeControllerBean.alertLeaderExceptionTotal start");
        }
        super._alertLeaderExceptionTotal(ctx);
        //中心负责人关系表
        ICenterLeaderRelation iCenterLeaderRelation = CenterLeaderRelationFactory.getLocalInstance(ctx);
        //获取中心负责人
        Map<String, Set<String>> leaders = iCenterLeaderRelation.getLeaders();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd E HH:mm:ss");
        //获取考勤异常数据,本周周一至周五中心考勤异常数据
        Calendar calendar = Calendar.getInstance();
        Date endDate = calendar.getTime();
        int intWeek = calendar.get(7);
        calendar.add(Calendar.DAY_OF_WEEK, 2 - intWeek);
        Date monday = calendar.getTime();
        logger.error("_alertLeaderExceptionTotal startDate: " + sdf.format(monday));
        if (intWeek > 6) {
            calendar.add(Calendar.DAY_OF_WEEK, 4);
            endDate = calendar.getTime();
        }
        logger.error("_alertLeaderExceptionTotal endDate: " + sdf.format(endDate));

        //getAttendanceExceptionData(ctx, monday, endDate);

        String url = "http://10.0.6.222:8888/ehr/api/syncAttendanceData";

        //pushAttendanceExceptionData(ctx, url, );

        //推送异常信息
        //sendAttendanceExceptionMsg(ctx);
        //推送异常数据
        if (logger.isInfoEnabled()) {
            long endTime = System.currentTimeMillis();
            float duration = (endTime - startTime) / 1000f;
            logger.info(String.format("AttendanceExceptionFacadeControllerBean.alertLeaderExceptionTotal end, duration: %fS", duration));
        }

    }

    /**
     * 获取考勤异常数据
     *
     * @param ctx
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @throws BOSException
     * @throws EASBizException
     */
    protected void getAttendanceExceptionData(
            Context ctx,
            Date startDate,
            Date endDate,
            String msgId,
            PushTypeEnum pushType,
            int limit
    ) throws BOSException, EASBizException {
        String sql = getSql(startDate, endDate);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            IRowSet iRowSet = DBUtil.executeQuery(ctx, sql);
            Map<String, List<SyncAttendanceDataBean>> result = new HashMap<>();
            Map<String, Integer> personExceptionTimes = new HashMap<>();
            if (!PushTypeEnum.CENTERLEADERREMINDER.equals(pushType)) {
                //非中心负责人提醒
                while (iRowSet.next()) {
                    SyncAttendanceDataBean data = new SyncAttendanceDataBean();
                    data.setMsgId(msgId);
                    String personNumber = iRowSet.getString("personNumber");
                    data.setEmployeeId(personNumber);
                    data.setEmployeeName(iRowSet.getString("personName"));
                    Date attenceDate = iRowSet.getDate("attenceDate");
                    if (attenceDate != null) {
                        data.setExceptionDate(sdf.format(attenceDate));
                    }
                    data.setDepartmentCode(iRowSet.getString("adminOrgNumber"));
                    data.setDepartmentName(iRowSet.getString("adminOrgName"));
                    data.setDepartmentManagerCode(iRowSet.getString("adminOrgLongNumber"));
                    data.setDepartmentSortCode(iRowSet.getString("sortCode"));
                    data.setDepartmentManagerName(iRowSet.getString("displayName"));
                    //String admintwoNumber = iRowSet.getString("admintwoNumber");
                    //String admintwoName = iRowSet.getString("admintwoName");
                    StringBuilder attendanceResult = new StringBuilder();
                    int times = 0;
                    Map<String, Boolean> attendanceFlags = new LinkedHashMap<>();
                    int s19 = iRowSet.getInt("s19");
                    int s21 = iRowSet.getInt("s21");
                    BigDecimal s23 = iRowSet.getBigDecimal("s23");
                    int s113 = iRowSet.getInt("s113");
                    attendanceFlags.put("迟到", s19 > 0);
                    attendanceFlags.put("早退", s21 > 0);
                    attendanceFlags.put("旷工", s23.compareTo(BigDecimal.ZERO) > 0);
                    attendanceFlags.put("个人原因补卡次数", s113 > 0);
                    for (Map.Entry<String, Boolean> entry : attendanceFlags.entrySet()) {
                        if (entry.getValue()) {
                            times++;
                            attendanceResult.append(entry.getKey()).append("、");
                        }
                    }
                    // 移除最后一个顿号
                    if (attendanceResult.length() > 0) {
                        attendanceResult.setLength(attendanceResult.length() - 1);
                    }
                    //累计员工期间总异常次数
                    if (personExceptionTimes.containsKey(personNumber)) {
                        Integer i = personExceptionTimes.get(personNumber);
                        personExceptionTimes.put(personNumber, i + times);
                    } else {
                        personExceptionTimes.put(personNumber, times);
                    }
                    data.setTimes(times);
                    data.setAttendanceResult(attendanceResult.toString());
                    if (!result.containsKey(personNumber)) {
                        result.put(personNumber, new ArrayList<>());
                    }
                    result.get(personNumber).add(data);
                }
                if (PushTypeEnum.EMPLOYEEEXCEPTIONALERT.equals(pushType)) {
                    //员工累计异常提醒
                    for (Map.Entry<String, Integer> entry : personExceptionTimes.entrySet()) {
                        if (entry.getValue() < limit) {
                            //移除没有达到预警上限的数据
                            result.remove(entry.getKey());
                        }
                    }
                }
            } else {
                while (iRowSet.next()) {
                    SyncAttendanceDataBean data = new SyncAttendanceDataBean();
                    data.setMsgId(msgId);
                    String personNumber = iRowSet.getString("personNumber");
                    data.setEmployeeId(personNumber);
                    data.setEmployeeName(iRowSet.getString("personName"));
                    Date attenceDate = iRowSet.getDate("attenceDate");
                    if (attenceDate != null) {
                        data.setExceptionDate(sdf.format(attenceDate));
                    }
                    data.setDepartmentCode(iRowSet.getString("adminOrgNumber"));
                    data.setDepartmentName(iRowSet.getString("adminOrgName"));
                    data.setDepartmentManagerCode(iRowSet.getString("adminOrgLongNumber"));
                    data.setDepartmentSortCode(iRowSet.getString("sortCode"));
                    data.setDepartmentManagerName(iRowSet.getString("displayName"));
                    String admintwoNumber = iRowSet.getString("admintwoNumber");
                    StringBuilder attendanceResult = new StringBuilder();
                    int times = 0;
                    Map<String, Boolean> attendanceFlags = new LinkedHashMap<>();
                    int s19 = iRowSet.getInt("s19");
                    int s21 = iRowSet.getInt("s21");
                    BigDecimal s23 = iRowSet.getBigDecimal("s23");
                    int s113 = iRowSet.getInt("s113");
                    attendanceFlags.put("迟到", s19 > 0);
                    attendanceFlags.put("早退", s21 > 0);
                    attendanceFlags.put("旷工", s23.compareTo(BigDecimal.ZERO) > 0);
                    attendanceFlags.put("个人原因补卡次数", s113 > 0);
                    for (Map.Entry<String, Boolean> entry : attendanceFlags.entrySet()) {
                        if (entry.getValue()) {
                            times++;
                            attendanceResult.append(entry.getKey()).append("、");
                        }
                    }
                    // 移除最后一个顿号
                    if (attendanceResult.length() > 0) {
                        attendanceResult.setLength(attendanceResult.length() - 1);
                    }
                    data.setTimes(times);
                    data.setAttendanceResult(attendanceResult.toString());
                    if (!result.containsKey(admintwoNumber)) {
                        result.put(admintwoNumber, new ArrayList<>());
                    }
                    result.get(admintwoNumber).add(data);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 获取考勤异常查询sql
     *
     * @param startDate
     * @param endDate
     * @return
     * @throws BOSException
     */
    protected String getSql(
            Date startDate,
            Date endDate
    ) throws BOSException {
        if (startDate == null || endDate == null) {
            logger.error("getAttendanceExceptionData startDate or endDate is null");
            throw new BOSException("getAttendanceExceptionData startDate or endDate is null");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        StringBuilder sql = new StringBuilder()
                .append("select").append("\n")
                .append("    person.fid as personId,").append("\n")
                .append("    person.fnumber as personNumber,").append("\n")
                .append("    person.Fname_l2 as personName,").append("\n")
                .append("    attendanceResult.FAttenceDate as attenceDate,").append("\n")
                .append("    attendanceResult.s19 as s19,").append("\n")
                .append("    attendanceResult.s21 as s21,").append("\n")
                .append("    attendanceResult.s23 as s23,").append("\n")
                .append("    attendanceResult.s113 as s113,").append("\n")
                .append("    adminOrg.fid as adminOrgId,").append("\n")
                .append("    adminOrg.fnumber as adminOrgNumber,").append("\n")
                .append("    adminOrg.fname_l2 as adminOrgName,").append("\n")
                .append("    adminOrg.FLongNumber as adminOrgLongNumber,").append("\n")
                .append("    adminOrg.FSortCode as sortCode,").append("\n")
                .append("    adminOrg.FDisplayName_L2 as displayName,").append("\n")
                .append("    admintow.fid as admintowId,").append("\n")
                .append("    admintow.fnumber as admintowNumber,").append("\n")
                .append("    admintow.Fname_l2 as admintowName").append("\n")
                .append("from").append("\n")
                .append("    T_HR_ATS_AttendanceResult attendanceResult").append("\n")
                .append("    left join t_bd_person person on person.fid = attendanceResult.FProposerID").append("\n")
                .append("    left join T_ORG_admin adminOrg on attendanceResult.FAdminOrgUnitID = adminOrg.fid").append("\n")
                .append("    left join T_ORG_admin admintow on adminOrg.FLevelTwoGroupID = admintow.fid").append("\n")
                .append("where").append("\n")
                .append("    attendanceResult.FAttenceDate >= { TS '").append(sdf.format(startDate)).append("' }").append("\n")
                .append("    and attendanceResult.FAttenceDate <= { TS '").append(sdf.format(endDate)).append("' }").append("\n")
                .append("    and (").append("\n")
                .append("        attendanceResult.s19 > 0").append("\n")
                .append("        or attendanceResult.s21 > 0").append("\n")
                .append("        or attendanceResult.s23 > 0").append("\n")
                .append("         or attendanceResult.S113 > 0").append("\n")
                .append("    );").append("\n");
        return sql.toString();
    }

    /**
     * 发送考勤异常消息
     *
     * @param ctx
     * @throws BOSException
     * @throws EASBizException
     */
    protected void sendAttendanceExceptionMsg(
            Context ctx,
            String url
    ) throws BOSException, EASBizException {

        try {
//            if (list == null || list.size() <= 0) {
//                logger.error("pushAttendanceExceptionData list is null");
//                throw new BOSException("pushAttendanceExceptionData list is null");
//            }
            if (url == null || url.isEmpty()) {
                logger.error("pushAttendanceExceptionData url is null");
                throw new BOSException("pushAttendanceExceptionData url is null");
            }
//            String params = JSON.toJSONString(list);
            //String url = "http://10.0.6.222:8888/ehr/api/syncAttendanceData";
            OkHttpClient client = new OkHttpClient();

            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, "{\r\n    \"msgId\": \"test_msg_id_12322\",\r\n    \"title\": \"考勤异常通知测试\",\r\n    \"content\": \"##### <font color=#6192f2>HR系统</font>\\n#### 员工考勤提醒：\\n您在2025年3月考勤异常次数已经达到5次，请您注意本月考勤 \\n###### (如有审批中的假勤单据，请及时催办)\",\r\n    \"toAllUser\": false,\r\n    \"alertUser\": \"SCY003987\",\r\n    \"alertType\": 2\r\n}");
            Request request = new Request.Builder()
                    .url("http://10.0.6.222:8888/ehr/api/sendDingMsg")
                    .post(body)
                    .addHeader("Accept", "*/*")
                    .addHeader("Accept-Encoding", "gzip, deflate, br")
                    .addHeader("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
                    .addHeader("Connection", "keep-alive")
                    .addHeader("Content-Type", "application/json")
                    .build();

            Response response = client.newCall(request).execute();
            logger.error("response----" + response.isSuccessful());
            if (response.isSuccessful()) {
                //ObjectMapper mapper = new ObjectMapper();
                String resultBody = response.body().string();
                logger.error("resultBody----" + resultBody);
                JSONObject result = JSONObject.parseObject(resultBody);
                logger.error("respMap----" + result);
                if (result.getBoolean("success")) {
                    //                    String data = result.get("data").toString();
                    //                    JSONArray jsonArray = JSONArray.parseArray(data);
                    //                    logger.error("jsonArray---" + jsonArray.toString());
                    //                    logger.error("jsonArray---" + jsonArray.size());
                    //                    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 i = 0; i < jsonArray.size(); i++) {
                    //                        JSONObject resultData = jsonArray.getJSONObject(i);
                    //                        //保存门禁打卡记录
                    //                    }
                } else {
                    //推送失败
                    String msg = result.getString("msg");
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 推送考勤异常数据
     *
     * @param ctx
     * @param msgId 消息id
     * @throws BOSException
     * @throws EASBizException
     */
    protected void pushAttendanceExceptionData(
            Context ctx,
            String url,
            List list
    ) throws BOSException, EASBizException {
        try {
            if (list == null || list.size() <= 0) {
                logger.error("pushAttendanceExceptionData list is null");
                throw new BOSException("pushAttendanceExceptionData list is null");
            }
            if (url == null || url.isEmpty()) {
                logger.error("pushAttendanceExceptionData url is null");
                throw new BOSException("pushAttendanceExceptionData url is null");
            }
            String params = JSON.toJSONString(list);
            //String url = "http://10.0.6.222:8888/ehr/api/syncAttendanceData";
            OkHttpClient client = new OkHttpClient();
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, params);
            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .addHeader("Accept", "*/*")
                    .addHeader("Accept-Encoding", "gzip, deflate, br")
                    .addHeader("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
                    .addHeader("Connection", "keep-alive")
                    .addHeader("Content-Type", "application/json")
                    .build();
            Response response = client.newCall(request).execute();
            logger.error("response----" + response.isSuccessful());
            if (response.isSuccessful()) {
                //ObjectMapper mapper = new ObjectMapper();
                String resultBody = response.body().string();
                logger.error("resultBody----" + resultBody);
                JSONObject result = JSONObject.parseObject(resultBody);
                logger.error("respMap----" + result);
                if (result.getBoolean("success")) {
//                    String data = result.get("data").toString();
//                    JSONArray jsonArray = JSONArray.parseArray(data);
//                    logger.error("jsonArray---" + jsonArray.toString());
//                    logger.error("jsonArray---" + jsonArray.size());
//                    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 i = 0; i < jsonArray.size(); i++) {
//                        JSONObject resultData = jsonArray.getJSONObject(i);
//                        //保存门禁打卡记录
//                    }
                } else {
                    //推送失败
                    String msg = result.getString("msg");
                }
            }

        } catch (IOException e) {
            logger.error("pushAttendanceExceptionData start", e);
            throw new RuntimeException(e);
        }
    }


}