package com.customization.yll.liuzhoucitycollege.integration;

import com.alibaba.fastjson.JSON;
import com.customization.yll.common.util.HrmInfoUtil;
import com.customization.yll.liuzhoucitycollege.api.JinzhiTokenManager;
import com.customization.yll.liuzhoucitycollege.config.JinzhiConfiguraton;
import com.customization.yll.liuzhoucitycollege.integration.bean.PushRecord;
import com.wisedu.casp.sdk.api.BaseResponse;
import com.wisedu.casp.sdk.api.Request;
import com.wisedu.casp.sdk.api.tdc.model.InsertModel;
import com.wisedu.casp.sdk.api.tdc.model.Processor;
import com.wisedu.casp.sdk.api.tdc.model.TaskModel;
import com.wisedu.casp.sdk.api.tdc.pushtask.SaveOrUpdateRequest;
import com.wisedu.casp.sdk.api.tdc.pushtask.TaskRealDeleteRequest;
import com.wisedu.casp.sdk.core.Client;
import com.wisedu.casp.sdk.core.DefaultClient;
import org.apache.commons.codec.binary.Hex;
import org.jetbrains.annotations.NotNull;
import weaver.conn.RecordSet;
import weaver.hrm.User;
import weaver.integration.logging.Logger;
import weaver.integration.logging.LoggerFactory;
import weaver.integration.util.ConstantsMethodUtil;
import weaver.ofs.interfaces.SendRequestStatusDataInterfaces;
import weaver.workflow.request.todo.DataObj;
import weaver.workflow.request.todo.RequestStatusObj;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author yaolilin
 * @desc 统一待办推送到金智，适用于金智接口 3.6.1.Beta2+ 版本
 * @date 2024/12/2
 **/
public class RequestSendToJinzhi implements SendRequestStatusDataInterfaces {
    private final JinzhiTokenManager tokenManager = new JinzhiTokenManager();
    private final Client client = new DefaultClient(JinzhiConfiguraton.getBaseUrl(),
            JinzhiConfiguraton.getAppId(), JinzhiConfiguraton.getAppSecret(), tokenManager.getTokenStore());
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    private final RequestPushLogRecorder pushLogRecorder = new RequestPushLogRecorder();
    /**
     * 统一待办推送配置id，自动传入
     */
    private String id;
    /**
     * 统一待办推送标识，自动传入
     */
    private String syscode;
    /**
     * 服务端地址，自动传入
     */
    private String serverurl;
    /**
     * mobile加密串，推送配置里配置参数传入
     */
    private String mobilekey;

    /**
     * mobile地址，推送配置里配置参数传入
     */
    private String mobileurl;

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public String getSyscode() {
        return this.syscode;
    }

    @Override
    public String getServerurl() {
        return this.serverurl;
    }

    @Override
    public ArrayList<String> getWorkflowwhitelist() {
        ArrayList<String> whiteWorkflowList = new ArrayList<>();
        RecordSet recordSet = new RecordSet();
        recordSet.executeQuery("SELECT workflowid from ofs_sendworkflow where mainid=?", this.id);
        while (recordSet.next()) {
            whiteWorkflowList.add(recordSet.getString("workflowid"));
        }
        return whiteWorkflowList;
    }

    @Override
    public ArrayList<String> getUserwhitelist() {
        RecordSet recordSet = new RecordSet();
        ArrayList<String> whiteUserList = new ArrayList<>();
        recordSet.executeQuery("select objid from ofs_senduser where type=1 and mainid=?", this.id);
        while (recordSet.next()) {
            whiteUserList.add(recordSet.getString("objid"));
        }
        return whiteUserList;
    }

    @Override
    public void SendRequestStatusData(ArrayList<DataObj> arrayList) {
        log.info("金智统一待办数据推送开始，流程数据：" + JSON.toJSONString(arrayList));
        try {
            for (DataObj data : arrayList) {
                pushTodoRequestData(data);
                pushDoneRequestData(data);
                pushDeleteRequestData(data);
            }
        } catch (Exception e) {
            log.error("金智统一待办推送出错", e);
        }
        log.info("金智统一待办数据推送结束");
    }

    /**
     * 推送待办流程数据
     *
     * @param data 流程数据
     */
    private void pushTodoRequestData(DataObj data) {
        ArrayList<InsertModel> insertModelList = new ArrayList<>();
        List<TaskModel> taskModelList = new ArrayList<>();
        List<PushRecord> pushRecords = new ArrayList<>();
        buildTodoRequestData(data, taskModelList, insertModelList, pushRecords);
        SaveOrUpdateRequest.UpdateModel updateModel = new SaveOrUpdateRequest.UpdateModel();
        updateModel.setTaskModels(taskModelList);
        log.info("insertModelList 添加任务 :" + JSON.toJSONString(insertModelList));
        log.info("taskModelList 更新任务：" + JSON.toJSONString(taskModelList));
        if (insertModelList.isEmpty() && taskModelList.isEmpty()) {
            return;
        }
        SaveOrUpdateRequest request = new SaveOrUpdateRequest();
        request.setInsertModel(insertModelList);
        request.setUpdateModel(updateModel);
        if (handleApiCall(request)) {
            pushRecords.forEach(pushLogRecorder::recordPush);
        }
    }

    private void buildTodoRequestData(DataObj data, List<TaskModel> taskModelList,
                                      ArrayList<InsertModel> insertModelList, List<PushRecord> pushRecords) {
        RecordSet recordSet = new RecordSet();
        ArrayList<RequestStatusObj> todoData = data.getTododatas();
        for (RequestStatusObj todo : todoData) {
            int userId = todo.getUser().getUID();
            if (userId == 1) {
                continue;
            }
            if (isUserExistRequest(todo.getRequestid(), userId)) {
                taskModelList.add(buildTaskModel(todo, true, recordSet));
            } else {
                insertModelList.add(buildInsertModel(todo, recordSet));
            }
            pushRecords.add(new PushRecord(todo.getRequestid(), userId, RequestPushLogRecorder.TODO_STATUS));
        }
    }

    /**
     * 推送已办流程数据
     *
     * @param data 流程数据
     */
    private void pushDoneRequestData(DataObj data) {
        List<PushRecord> pushRecords = new ArrayList<>();
        List<TaskModel> taskModelList = buildDoneRequestData(data, pushRecords);
        SaveOrUpdateRequest.UpdateModel updateModel = new SaveOrUpdateRequest.UpdateModel();
        updateModel.setTaskModels(taskModelList);
        log.info("taskModelList 更新上一个任务 ：" + JSON.toJSONString(taskModelList));
        if (taskModelList.isEmpty()) {
            return;
        }
        SaveOrUpdateRequest request = new SaveOrUpdateRequest();
        request.setUpdateModel(updateModel);
        if (handleApiCall(request)) {
            pushRecords.forEach(pushLogRecorder::recordPush);
        }
    }

    /**
     * 推送删除流程数据
     *
     * @param data 流程数据
     */
    private void pushDeleteRequestData(DataObj data) {
        for (RequestStatusObj delData : data.getDeldatas()) {
            // 金智那边没有这条流程数据则跳过
            int userId = delData.getUser().getUID();
            if (userId == 1 || !isUserExistRequest(delData.getRequestid(), userId)) {
                continue;
            }
            String taskId = getTaskId(delData.getRequestid() + "", delData.getUser().getLoginid());
            log.info("删除流程：" + taskId);
            TaskRealDeleteRequest request = new TaskRealDeleteRequest();
            request.setTaskId(taskId);
            if (handleApiCall(request)) {
                pushLogRecorder.recordPush(new PushRecord(delData.getRequestid(), userId,
                        RequestPushLogRecorder.DELETE_STATUS));
            }
        }
    }

    private List<TaskModel> buildDoneRequestData(DataObj data, List<PushRecord> pushRecords) {
        RecordSet recordSet = new RecordSet();
        List<TaskModel> taskModelList = new ArrayList<>();
        for (RequestStatusObj doneData : data.getDonedatas()) {
            int userId = doneData.getUser().getUID();
            if (userId == 1 || !isUserExistRequest(doneData.getRequestid(), userId)) {
                continue;
            }
            taskModelList.add(buildTaskModel(doneData, false, recordSet));
            pushRecords.add(new PushRecord(doneData.getRequestid(), userId, RequestPushLogRecorder.DONE_STATUS));
        }
        return taskModelList;
    }

    private String getTaskId(String requestId, String loginId) {
        return requestId + "_" + loginId;
    }

    private boolean handleApiCall(Request<BaseResponse> request) {
        try {
            BaseResponse response = client.execute(request);
            log.info("推送结果：" + response);
            if (!response.isSuccess()) {
                log.error("流程推送失败，" + response);
                return false;
            }
            log.info("推送成功");
            return true;
        } catch (Exception e) {
            log.error("流程推送发生异常", e);
            return false;
        }
    }

    @NotNull
    private TaskModel buildTaskModel(RequestStatusObj todo, boolean isTodo, RecordSet recordSet) {
        TaskModel taskModel = new TaskModel();
        taskModel.setTaskId(getTaskId(todo.getRequestid() + "", todo.getUser().getLoginid()));
        taskModel.setProcessorId(todo.getUser().getLoginid());
        taskModel.setStatus(getTaskStatus(todo, isTodo, recordSet));
        taskModel.setProcessorType(1);
        taskModel.setProcessInstanceImgUrl(getWorkflowGraphUrl(todo.getRequestid(), todo.getWorkflowid()));
        taskModel.setTaskComment(getRemark(todo.getRequestid(), recordSet));
        return taskModel;
    }

    private String getRemark(int requestId, RecordSet recordSet) {
        recordSet.executeQuery("select remark1 from workflow_requestlog where requestid=? order by logid desc"
                , requestId);
        recordSet.next();
        return recordSet.getString("remark1");
    }

    private String getTaskStatus(RequestStatusObj requestData, boolean isTodo, RecordSet recordSet) {
        if (isTodo) {
            return "ACTIVE";
        }
        String status;
        recordSet.executeQuery("select logtype from workflow_requestlog where operatedate=? and operatetime=? and " +
                        "operator=? and (logtype='3' or logtype='h')", requestData.getOperatedate(),
               requestData.getOperatetime(), requestData.getUser().getUID());
        recordSet.next();
        String logType = recordSet.getString("logtype");
        if ("2".equals(requestData.getIsremark())) {
            // 流程为已操作时，判断操作者的操作是否为退回或转办
            if ("3".equals(logType)) {
                // 操作为退回
                status = "ROLLBACK";
            } else if ("h".equals(logType)) {
                // 操作为转办
                status = "DELEGATE";
            } else {
                status = "COMPLETE";
            }
        } else if ("4".equals(requestData.getIsremark())) {
            status = "COMPLETE";
        }else {
            status = "ACTIVE";
        }
        return status;
    }

    @NotNull
    private InsertModel buildInsertModel(RequestStatusObj todo, RecordSet recordSet) {
        InsertModel insertModel = new InsertModel();
        insertModel.setTaskId(getTaskId(todo.getRequestid() + "", todo.getUser().getLoginid()));
        insertModel.setSceneCode(JinzhiConfiguraton.getSceneCode());
        insertModel.setSubject(todo.getRequstname());
        insertModel.setPriority(getPriority(todo.getRequestid(),recordSet));
        insertModel.setTaskType(3);
        insertModel.setInitiatorType(1);
        insertModel.setInitiatorId(todo.getCreator().getLoginid());
        insertModel.setProcessors(getProcessors(todo.getUser()));
        insertModel.setPrevProcessor(getPrevProcessor(todo, recordSet));
        insertModel.setPcViewUrl(getPcUrl(todo.getRequestid() + ""));
        insertModel.setH5ViewUrl(getAppUrl(todo.getRequestid() + ""));
        insertModel.setProcessInstanceImgUrl(getWorkflowGraphUrl(todo.getRequestid(), todo.getWorkflowid()));
        insertModel.setNodeId(todo.getNodeid() + "");
        insertModel.setNodeName(todo.getNodename());
        insertModel.setCreateTime(todo.getCreatedate() + " " + todo.getCreatetime());
        return insertModel;
    }

    private boolean isUserExistRequest(int requestId, int userId) {
        Optional<Integer> requestStatus = pushLogRecorder.getRequestStatus(requestId, userId);
        return requestStatus.isPresent() && requestStatus.get() != RequestPushLogRecorder.DELETE_STATUS;
    }

    private int getPriority(int requestId,RecordSet recordSet) {
        recordSet.executeQuery("SELECT REQUESTLEVEL from workflow_requestbase where REQUESTID=?", requestId);
        recordSet.next();
        int requestLevel = recordSet.getInt("requestlevel");
        switch (requestLevel) {
            case 0:
                return 3;
            case 1:
                return 2;
            case 2:
            default:
                return 1;
        }
    }

    private List<Processor> getProcessors(User user) {
        String workCode = user.getLoginid();
        Processor processor = new Processor();
        processor.setProcessorType(1);
        processor.setProcessorId(workCode);
        return Stream.of(processor).collect(Collectors.toList());
    }

    private String getPrevProcessor(RequestStatusObj todo, RecordSet recordSet) {
        // 获取上一步的操作者
        recordSet.executeQuery("select operator,receivedpersonids from workflow_requestlog where" +
                        " requestid=? order by logid desc", todo.getRequestid());
        while (recordSet.next()) {
            List<String> receives = Arrays.stream(recordSet.getString("receivedpersonids")
                    .split(",")).collect(Collectors.toList());
            if (receives.contains(todo.getUser().getUID() + "")) {
                int operator = recordSet.getInt("operator");
                return HrmInfoUtil.getWorkCode(operator, recordSet);
            }
        }
        return "";
    }

    private String getWorkflowGraphUrl(int requestId, int workflowId) {
        String page = String.format("/workflow/workflowDesign/readOnly-index.html?" +
                "requestid=%s&workflowid=%s&isFromWfForm=true", requestId, workflowId);
        return ConstantsMethodUtil.getOaAddress() + page;
    }

    /**
     * 构造PC地址
     */
    private String getPcUrl(String requestId) {
        String oaAddress = ConstantsMethodUtil.getOaAddress();
        String gotoPage = String.format("/spa/workflow/static4form/index.html?_rdm=%s" +
                "#/main/workflow/req?requestid=%s", System.currentTimeMillis(), requestId);
        return oaAddress + gotoPage;
    }

    /**
     * 构造APP地址
     */
    private String getAppUrl(String requestid) {
        String page = String.format("/spa/workflow/static4mobileform/index.html?_random=%s#/req?requestid=%s",
                System.currentTimeMillis(), requestid);
        return mobileurl + page;
    }

    /**
     * 将字段串做SHA-1加密处理
     */
    private String hexSHA1(String value) {
        String result;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(value.getBytes("utf-8"));
            byte[] digest = md.digest();
            result = byteToHexString(digest);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result = "";
        }

        return result;
    }

    /**
     * 将byte转为16进制
     */
    public static String byteToHexString(byte[] bytes) {
        return String.valueOf(Hex.encodeHex(bytes));
    }
}
