package com.engine.custom.archives.workflow.biz.requestLog;

import com.alibaba.fastjson.JSONObject;
import com.api.doc.detail.util.DocDownloadCheckUtil;
import com.engine.workflow.biz.RobotNode.RobotNodeBiz;
import com.engine.workflow.biz.RobotNode.RobotNodeServiceBiz;
import com.engine.workflow.biz.freeNode.FreeNodeBiz;
import com.engine.workflow.biz.workflowCore.WorkflowBaseBiz;
import com.engine.workflow.constant.RequestLogType;
import com.engine.workflow.constant.SignSource;
import com.engine.workflow.constant.node.NodeType;
import com.engine.workflow.entity.core.NodeInfoEntity;
import com.engine.workflow.entity.requestLog.RequestLogEntity;
import com.engine.workflow.util.CollectionUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import weaver.conn.ConnStatement;
import weaver.conn.RecordSet;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.workflow.request.RequestOperationMsgManager;
import weaver.workflow.request.RequestSignRelevanceWithMe;
import weaver.workflow.request.WFLinkInfo;
import weaver.workflow.request.WorkflowSpeechAppend;
import weaver.workflow.workflow.WorkflowVersion;

import java.util.*;

/**
 * 获取签字意见
 * Created by jhy on 2018/11/7.
 */
public class RequestLogCusBiz {

    public static Logger log = LoggerFactory.getLogger("Archives");

    /**
     * 获得流程流转日志总记录数
     *
     * @param requestid
     * @param workflowid
     * @param viewLogIds
     * @return
     */
    public static int getRequestLogTotalCount(int requestid, int workflowid, String viewLogIds, String sqlwhere) {
        RecordSet rs = new RecordSet();
        String thisviewLogIds = getViewLogIds(viewLogIds, requestid, workflowid);
        //需要排除不留痕的机器人节点的id
        String robotNodeid = getRobotNodeid(thisviewLogIds);

        String sql = "select count(t1.logid) from workflow_requestlog t1 " +
                " where t1.requestid=" + requestid + " and t1.logtype != '1' " +
                " and " + Util.getSubINClause(thisviewLogIds, "t1.nodeid", "in") + "  " + sqlwhere;
        ArrayList unshowlogids = forkStartLogids(requestid, workflowid);
        if (unshowlogids.size() > 0) {
            sql += " and " + Util.getSubINClause(StringUtils.join(unshowlogids, ","), "t1.logid", "not in");
        }

        if(!"".equals(robotNodeid)){
            sql += " and logid not in (select logid from workflow_requestlog where "+Util.getSubINClause(robotNodeid, "t1.nodeid", "in")+" and operator = '0' and isRobotNode='1')";
        }
        rs.executeSql(sql);
        int logcount = 0;
        if (rs.next()) logcount = rs.getInt(1);
        return logcount;
    }

    //得到不留痕的机器人节点的id
    public static  String getRobotNodeid(String thisviewLogIds){
        //需要排除不留痕的机器人节点的id
        String robotNodeid = "";
        String[] thisviewLogIdsArr = thisviewLogIds.split(",");
        for (String viewLogId : thisviewLogIdsArr) {
            int viewnodeid = Util.getIntValue(viewLogId,-1);
            NodeInfoEntity nodeInfoEntity = WorkflowBaseBiz.getNodeInfo(viewnodeid);
            if(NodeType.WAIT.getValue().equals(nodeInfoEntity.getNodetype()+"") || NodeType.AUTOPROCESS.getValue().equals(nodeInfoEntity.getNodetype()+"")){
                String remarkOperation = new RobotNodeServiceBiz().getRobotNodeSet(viewnodeid).getRemarkOperation();
                if("0".equals(remarkOperation)){
                    robotNodeid += "," + viewLogId;
                }
            }
        }
        if(robotNodeid.startsWith(",")){
            robotNodeid = robotNodeid.substring(1);
        }
        return robotNodeid;
    }

    /**
     * 获得流程流转日志
     *
     * @param requestid
     * @param workflowid
     * @param viewLogIds
     * @return
     */
    public static ArrayList getRequestLog(int requestid, int workflowid, String viewLogIds, String orderby, int pageSize, int pagenumber, String sqlwhere , boolean isSubrequest) {
        ArrayList logs = new ArrayList();
        RecordSet rs = new RecordSet();
        pageSize = 999999;
        int min = (pagenumber - 1) * pageSize;
        int max = pagenumber * pageSize;

        String sql = getLogSql(requestid, workflowid, viewLogIds, orderby, sqlwhere ,isSubrequest);
        log.error("requestlogsql==>"+ sql);
        StringBuffer splitinertSql = new StringBuffer();
        if ("sqlserver".equals(rs.getDBType())) {
            splitinertSql.append(" select * from ( select");
            splitinertSql.append(" row_number() over(order by tbl.operatedate ").append(orderby).append(",tbl.operatetime ").append(orderby).append(", tbl.logid ").append(orderby).append(") as rn,* from (");
            splitinertSql.append(sql).append(" ) tbl ");
            splitinertSql.append(") t where rn > ").append(min).append(" and rn <= ").append(max);
        } else if ("mysql".equals(rs.getDBType())) {
            splitinertSql.append(sql).append(" limit ").append(min).append(",").append(pageSize);
        }
        else if ("postgresql".equals(rs.getDBType())) {
            splitinertSql.append(sql).append(" limit ").append(pageSize).append(" offset ").append(min);
        }
        else {
            splitinertSql.append(" select t1.* from (");
            splitinertSql.append(" select t.*,rownum rn from (" + sql + ") t ");
            splitinertSql.append(" ) t1 where rn >").append(min).append(" and rn <=").append(max);
        }
        log.error("splitinertSql:{}"+splitinertSql);
        rs.execute(splitinertSql.toString());
        while (rs.next()) {
            Hashtable hashtable = addLogItem(rs);
            if(hashtable != null) logs.add(hashtable);
        }
        //对log中的重复数据进行清除
        logs = uniqLogs(logs);
        return logs;
    }

    public static String getLogSql(int requestid, int workflowid, String viewLogIds, String orderby, String sqlwhere, boolean isSubrequest) {
        RecordSet rs = new RecordSet();
        String mainAndSubRequestId = getMainOrSubRequest(requestid,isSubrequest);
        if (orderby == null || orderby.trim().equals("")) orderby = "desc";
        String mssqlTopflg = "";
        if ("sqlserver".equals((rs.getDBType()))) {
            mssqlTopflg = " top 100 percent ";
        }
        String thisviewLogIds = getViewLogIds(viewLogIds, requestid, workflowid);
        String autoInitNodeIds = getAutoInitNodeIds(workflowid);
        String robotNodeid = getRobotNodeid(thisviewLogIds);
        String selectfields = "  nodeid,destnodeid,operatedate,operatetime,logtype,remark,isMobile,logid,operatortype,operator," +
                "agenttype,agentorbyagentid,receivedPersonids,requestLogId,annexdocids,operatorDept,signdocids," +
                "signworkflowids,fulltextannotation,HandWrittenSign,SpeechAttachment,speechAttachmente9,remarkLocation,isRobotNode";
        if ("sqlserver".equals(rs.getDBType())) {
            selectfields += ",left(substring(receivedPersons,0,2000),240) as receivedPersons ";
        } else if ("oracle".equalsIgnoreCase(rs.getDBType())) {
            selectfields += ",substr(receivedPersons,0,240) as receivedPersons ";
        } else if ("mysql".equalsIgnoreCase(rs.getDBType())) {
            selectfields += ",left(receivedPersons,240) as receivedPersons ";
        } else {
            selectfields += ",receivedPersons";
        }

        String sql = "select " + mssqlTopflg + selectfields + "  from workflow_requestlog t1 " +
                " where t1.requestid in ( " + mainAndSubRequestId + ") and t1.logtype != '1' " +
                " and t1.nodeid not in (" +  autoInitNodeIds + " )" + " " +
                " and t1.operator != 1 and t1.OPERATOR != (select id from HRMRESOURCE where loginid = 'fenfa')";
        if (sqlwhere != null && !sqlwhere.equals("")) {
            sql = sql + sqlwhere;
        }

        ArrayList unshowlogids = forkStartLogids(requestid, workflowid);
        if (unshowlogids.size() > 0) {
            sql += " and " + Util.getSubINClause(StringUtils.join(unshowlogids, ","), "t1.logid", "not in");
        }
        if(!"".equals(robotNodeid)){
            sql += " and logid not in (select logid from workflow_requestlog where "+Util.getSubINClause(robotNodeid, "t1.nodeid", "in")+" and operator = '0' and isRobotNode='1')";
        }
        sql = sql + " order by t1.operatedate " + orderby + ",t1.operatetime " + orderby + ",t1.logtype " + orderby + ",t1.logid " + orderby;
        log.error("sqlsql:"+sql);
        return sql;
    }

    /**
     * 获取流程自动发起的节点
     * @param mainAndSubRequestId
     * @return
     */
    // private static String   getAutoInitNodeIds(String mainAndSubRequestId) {
    private static String   getAutoInitNodeIds(int workflowid) {
        RecordSet recordSet = new RecordSet();
        // ArrayList<String> nodeids = new ArrayList<>();
        // String sql = "select node.NODEID nodeid ,  nodegroup.GROUPNAME from  workflow_flownode node " +
        //         "                     left join workflow_nodegroup nodegroup " +
        //         "                               on node.nodeid = nodegroup.nodeid " +
        //         "                                            left join workflow_groupdetail detail " +
        //         "on nodegroup.id = detail.GROUPID " +
        //         "where node.WORKFLOWID in (select distinct WORKFLOWID from WORKFLOW_REQUESTBASE where REQUESTID in ( "+ mainAndSubRequestId +" ) ) and detail.id is null";
        String sql = "select * from uf_ArchivesSet where mainwfid = ? ";
        recordSet.executeQuery(sql,workflowid);
        // while (recordSet.next()){
        //     String nodeid = recordSet.getString("nodeid");
        //     if (!StringUtils.isEmpty(nodeid)){
        //         nodeids.add(nodeid);
        //     }
        // }
        if (recordSet.next()){
            return recordSet.getString("exclusenodeid");
        }
        return "1";
    }

    private static String getMainOrSubRequest(int requestid, boolean isSubrequest) {
        log.error("isSubrequest:"+isSubrequest);
        if (isSubrequest){

            List<String> reqids = new ArrayList<>();
            RecordSet rs = new RecordSet();
            String ids = requestid+"";
            reqids.add(requestid+"");
            for (int i = 0; i < 5; i++) {
                ArrayList<String> idList = new ArrayList<>();
                String sql = "select requestid , workflowid from workflow_requestbase where mainrequestid in ( " + ids + " )";
                log.error("subrequestSql:" + sql);
                rs.executeQuery(sql);
                while (rs.next()) {
                    String subrequestid = Util.null2String(rs.getString("requestid"));
                    // String workflowid = Util.null2String(rs.getString("workflowid"));
                    idList.add(subrequestid);
                    reqids.add(subrequestid);
                    // 使用map自动去重,一种流程类型只取一个requestid

                }
                ids = String.join(",", idList);
                if (ids.length() == 0) {
                    break;
                }
            }
            log.error("子流程的id:"+String.join(",", reqids));
            return String.join(",", reqids);
        }else {
            RecordSet recordSet = new RecordSet();
            recordSet.executeQuery("select * from WORKFLOW_REQUESTBASE where REQUESTID = ?",requestid);
            String wfid = "";
            if (recordSet.next()){
                wfid = Util.null2String(recordSet.getString("WORKFLOWID"));
            }
            recordSet.executeQuery("select * from uf_ArchivesSet where mainwfid = ? ",wfid);
            String mainwfid = "";
            String subwfid = "";
            if(recordSet.next()){
                mainwfid = Util.null2String(recordSet.getString("mainwfid"));
                subwfid = Util.null2String(recordSet.getString("subwfid"));
            }else {
                return Util.null2String(requestid);
            }
            List<String> reqids = new ArrayList<>();
            reqids.add(requestid+"");
            String ids = requestid+"";
            for (int i = 0; i < 5; i++) {
                ArrayList<String> idList = new ArrayList<>();
                String sql = "select requestid , workflowid from workflow_requestbase where mainrequestid in ( " + ids + " ) and workflowid in ( " + subwfid + " ) ";
                log.error("subrequestSql:" + sql);
                recordSet.executeQuery(sql);
                while (recordSet.next()) {
                    String subrequestid = Util.null2String(recordSet.getString("requestid"));
                    // String workflowid = Util.null2String(rs.getString("workflowid"));
                    idList.add(subrequestid);
                    reqids.add(subrequestid);
                    // 使用map自动去重,一种流程类型只取一个requestid

                }
                ids = String.join(",", idList);
                if (ids.length() == 0) {
                    break;
                }
            }
            log.error("子流程的id:"+String.join(",", reqids));
            return String.join(",", reqids);
        }

    }

    public static String getLogCountSql(int requestid, int workflowid, String viewLogIds, String orderby, String sqlwhere){
        String thisviewLogIds = getViewLogIds(viewLogIds, requestid, workflowid);

        String sql = "select count(*) as count from workflow_requestlog t1 " +
                " where t1.requestid=" + requestid + " and t1.logtype != '1' " +
                " and " + Util.getSubINClause(thisviewLogIds, "t1.nodeid", "in");
        if (sqlwhere != null && !sqlwhere.equals("")) {
            sql = sql + sqlwhere;
        }

        ArrayList unshowlogids = forkStartLogids(requestid, workflowid);
        if (unshowlogids.size() > 0) {
            sql += " and " + Util.getSubINClause(StringUtils.join(unshowlogids, ","), "t1.logid", "not in");
        }
        return sql;
    }

    /**
     * 判断签字意见是否加载完毕
     *
     */
    public static boolean isEndLog(int requestid, int workflowid, String viewLogIds, String orderby, int pageSize, int pagenumber, String sqlwhere) {
        RecordSet rs = new RecordSet();
        int max = pagenumber * pageSize;
        String sql =getLogCountSql(requestid, workflowid, viewLogIds, orderby, sqlwhere);
        rs.executeQuery(sql);
        int count = 0;
        if(rs.next()){
            count = rs.getInt("count");
        }
        if(count<=max){
            return true;
        }else{
            return false;
        }
    }

    private static Hashtable addLogItem(RecordSet rs) {
        int log_nodeid = rs.getInt("nodeid");
        int log_destnodeid = rs.getInt("destnodeid");
        String operatedate = Util.null2String(rs.getString("operatedate"));
        String operatetime = Util.null2String(rs.getString("operatetime"));
        String log_logtype = Util.null2String(rs.getString("logtype"));
        String isRobotNode = Util.null2String(rs.getString("isRobotNode"));
        Hashtable htlog = new Hashtable();
        String remarkHtml = rs.getString("remark");
        String isMobile = Util.null2String(rs.getString("isMobile"));
        htlog.put("nodeid", "" + log_nodeid);
        htlog.put("isRobotNode", "" + isRobotNode);

        NodeInfoEntity nodeInfoEntity = WorkflowBaseBiz.getNodeInfo(log_nodeid);
        String operator = rs.getString("operator");
        if(operator.equals(RobotNodeBiz.operatorid) && (NodeType.WAIT.getValue().equals(nodeInfoEntity.getNodetype()+"") || NodeType.AUTOPROCESS.getValue().equals(nodeInfoEntity.getNodetype()+""))){
            //机器人节点
            String remarkOperation = new RobotNodeServiceBiz().getRobotNodeSet(log_nodeid).getRemarkOperation();
            if("0".equals(remarkOperation) && "1".equals(isRobotNode)){
                return null;
            }
        }
        htlog.put("nodeattribute", nodeInfoEntity.getNodeAttribute());
        htlog.put("nodename", nodeInfoEntity.getNodename());
        htlog.put("destnodeid", "" + log_destnodeid);
        htlog.put("iframeId", "FCKsigniframe" + rs.getInt("logid"));
        htlog.put("operatortype", rs.getString("operatortype"));
        htlog.put("operator", rs.getString("operator"));
        htlog.put("agenttype", rs.getString("agenttype"));
        htlog.put("agentorbyagentid", rs.getString("agentorbyagentid"));
        htlog.put("operatedate", operatedate);
        htlog.put("operatetime", operatetime);
        htlog.put("logtype", log_logtype);
        htlog.put("receivedPersons", rs.getString("receivedPersons"));
        htlog.put("receivedPersonids", rs.getString("receivedPersonids"));
        htlog.put("logid", rs.getString("requestLogId"));
        htlog.put("tmpLogId", rs.getString("logid"));
        htlog.put("annexdocids", rs.getString("annexdocids"));
        htlog.put("operatorDept", rs.getString("operatorDept"));
        htlog.put("signdocids", rs.getString("signdocids"));
        htlog.put("signworkflowids", rs.getString("signworkflowids"));
        htlog.put("fulltextannotation", rs.getString("fulltextannotation"));
        htlog.put("isMobile", isMobile);

        htlog.put("handwrittensignid", Util.null2String(rs.getString("HandWrittenSign"), ""));
        htlog.put("speechattachmentid", Util.getIntValue(rs.getString("SpeechAttachment"), 0));
        htlog.put("speechAttachmente9", rs.getString("speechAttachmente9"));

        htlog.put("remarkLocation", rs.getString("remarkLocation"));
        htlog.put("id", rs.getString("logid"));

        //处理手机版中所添加的来源的后缀。
        String mobileSuffix = null;
        //处理历史数据
        SignSource signSource = SignSource.getSignSource(isMobile);
        if (signSource != null) {
            mobileSuffix = WorkflowSpeechAppend.getMobileSuffix(remarkHtml);
            if (mobileSuffix != null) {
                remarkHtml = remarkHtml.substring(0, remarkHtml.lastIndexOf(mobileSuffix));
            }
        }

        //获取签字意见中的电子签章部分。
        String eletriSignature = WorkflowSpeechAppend.getElectrSignatrue(remarkHtml);
        if (eletriSignature != null) {
            remarkHtml = remarkHtml.substring(0, remarkHtml.lastIndexOf(eletriSignature));
        }

        //获取并设置手写签批和语音附件内容
        String attachmentID = Util.null2String(rs.getString("HandWrittenSign"), "");
        if (!"".equals(attachmentID)) {
            String[] attachmentids = attachmentID.split(",");
            for (int i = 0; i < attachmentids.length; i++) {
                int attachmentid = Util.getIntValue(attachmentids[i]);
                if (attachmentid > 0) {
                    String attachmentidAes = DocDownloadCheckUtil.checkPermission(String.valueOf(attachmentid), null);
                    remarkHtml += "<BR/><img name=\"handWrittenSign\" src=\""+weaver.general.GCONST.getContextPath()+"/weaver/weaver.file.FileDownload?fileid=" + attachmentidAes + "\" />";
                }
            }
        }
        //全文批注
        String fulltextannotation = Util.null2String(rs.getString("fulltextannotation")).trim();
        if (!"".equals(fulltextannotation)) {
            String[] fulltextannotationIds = Util.splitString(fulltextannotation, ",");
            for (String fulltextannotationId : fulltextannotationIds) {
                int __fulltextannoationid = Util.getIntValue(fulltextannotationId);
                if (__fulltextannoationid <= 0) continue;
                remarkHtml += "<BR/><img name=\"fulltextannotation\" src=\""+weaver.general.GCONST.getContextPath()+"/weaver/weaver.file.FileDownload?fileid=" + __fulltextannoationid + "\" />";
            }
        }
        int attachmentID1 = Util.getIntValue(rs.getString("SpeechAttachment"), 0);
        if (attachmentID1 > 0) {
            remarkHtml += "<BR/><embed name=\"speechAttachment\" height=\"25px\" width=\"300px\" name=\"speechPlayer\" src=\"audioPlayer.swf?audioUrl="+weaver.general.GCONST.getContextPath()+"/weaver/weaver.file.FileDownload?fileid=" + attachmentID1 + "\" type=\"application/x-shockwave-flash\"/>";
        }

        //再加上电子签章和来源信息。
        if (eletriSignature != null) {
            remarkHtml += eletriSignature;
        }
        if (mobileSuffix != null) {
            remarkHtml += mobileSuffix;
        }
        htlog.put("remarkHtml", remarkHtml);
        htlog.put("isbranche", "1".equals(nodeInfoEntity.getNodeAttribute()) ? "1" : "0");
        return htlog;
    }

    private static String getViewLogIds(String viewLogIds, int requestid, int workflowid) {
        if ("".equals(viewLogIds)) {
            viewLogIds = "-1";
        }

        if (viewLogIds.lastIndexOf(",") == viewLogIds.length() - 1) {
            viewLogIds = viewLogIds.substring(0, viewLogIds.length() - 1);
        }
        //查找可查看节点发起的自由节点
        String _freenodeids = getFreeNodeidsByNodeids(requestid + "", viewLogIds);
        if (!"".equals(viewLogIds) && !"".equals(_freenodeids)) {
            viewLogIds += "," + _freenodeids;
        }

        String thisrequestnodeid = getAllNodeids4Request(requestid, workflowid);
        return checkNodeids(thisrequestnodeid, viewLogIds);
    }

    public static String getFreeNodeidsByNodeids(String requestid, String nodeids) {
        String result = "";
        if (nodeids == null || "".equals(nodeids)) return result;
        if (nodeids.endsWith(",")) {
            nodeids = nodeids.substring(0, nodeids.lastIndexOf(","));
        }
        String sql = "select id from workflow_nodebase where isfreenode=1 and requestid=" + requestid + " and " + Util.getSubINClause(nodeids, "startnodeid", "in");
        RecordSet rs = new RecordSet();
        rs.executeSql(sql);
        while (rs.next()) {
            result += "," + Util.null2String(rs.getString(1));
        }
        if (result.length() > 1) {
            result = result.substring(1);
        }
        return result;
    }

    /**
     * 查找到当前请求有关的所有节点的ID，包括路径设置里设置的和自由流程的节点
     *
     * @param requestid
     * @param workflowid
     * @return
     */
    public static String getAllNodeids4Request(int requestid, int workflowid) {
        StringBuffer sb = new StringBuffer();
        try {
            String allWfId = WorkflowVersion.getAllVersionStringByWFIDs(String.valueOf(workflowid));
            RecordSet recordSet = new RecordSet();
            recordSet.execute("select nb.id from workflow_nodebase nb left join workflow_flownode fn on nb.id=fn.nodeid where (nb.IsFreeNode is null or nb.IsFreeNode!='1' or (nb.IsFreeNode='1' and nb.requestid=" + requestid + ")) and " + Util.getSubINClause(allWfId, "fn.workflowid"," in"));
            while (recordSet.next()) {
                int id_tmp = Util.getIntValue(recordSet.getString(1));
                sb.append("," + id_tmp);
            }
            sb.append(",");
        } catch (Exception e) {
            //
        }
        return sb.toString();
    }

    /**
     * 筛选节点ID，只留下和当前请求有关的，主要是去掉同workflowid下的其他请求的自由流程节点
     *
     * @param thisnodeids:这个requestid对应的workflowid的所有节点和requestid下的所有自由流程节点
     * @param nodeids:待筛选的节点，一般是当前操作用户有权限查看签字意见的所有节点
     * @return
     */
    public static String checkNodeids(String thisnodeids, String nodeids) {
        StringBuffer sb = new StringBuffer();
        nodeids = Util.null2String(nodeids);
        thisnodeids = Util.null2String(thisnodeids);
        if (!"".equals(nodeids) && !"".equals(thisnodeids)) {
            try {
                String[] nodeid_sz = nodeids.split(",");
                for (int cx = 0; cx < nodeid_sz.length; cx++) {
                    int nodeid_tmp = Util.getIntValue(Util.null2String(nodeid_sz[cx]).trim());
                    //E9新版自由流程
                    if (nodeid_tmp < -1) {
                        sb.append(nodeid_tmp + ",");
                    } else {
                        if (("," + thisnodeids + ",").indexOf("," + nodeid_tmp + ",") > -1) {
                            sb.append(nodeid_tmp + ",");
                        }
                    }
                }
                if (sb.length() > 0) {
                    sb.delete(sb.length() - 1, sb.length());
                }
            } catch (Exception e) {
                //
            }
        }
        if (sb.length() == 0) {
            sb.append("-1");
        }
        return sb.toString();
    }

    /**
     * 查询需要过滤的分叉起始节点的签字意见,排除最后一个
     *
     * @param requestid
     * @param workflowid
     * @return
     */
    public static ArrayList forkStartLogids(int requestid, int workflowid) {
        ArrayList logids = new ArrayList();
        RecordSet rs = new RecordSet();
        RecordSet rs1 = new RecordSet();
        String c_sql = "";
        rs.executeSql("select 1 from workflow_flownode f ,workflow_nodebase n where f.workflowid=" + workflowid + " and f.nodeid=n.id and n.nodeattribute=1");//通过分叉起始节点判断是否为分叉流程
        if (rs.next()) {
            //rs.executeSql("select nodeid,nodename from workflow_flownode f,workflow_nodebase n WHERE workflowid="+workflowid+" AND n.id=f.nodeid and (n.IsFreeNode is null or n.IsFreeNode!='1')  ");
            rs.executeSql("select nodeid,nodename from workflow_flownode f,workflow_nodebase n WHERE workflowid=" + workflowid + " AND n.id=f.nodeid and (n.IsFreeNode is null or n.IsFreeNode!='1')  and n.nodeattribute not in ('2') and exists (select 1 from workflow_requestlog l where l.requestid=" + requestid + " and l.nodeid=f.nodeid and l.logtype in ('0','2','3') group by l.logid having(l.logid)>1) ");
            while (rs.next()) {
                String nodeid = rs.getString("nodeid");
                String nodename = rs.getString("nodename");
                c_sql = "SELECT a.LOGID FROM workflow_requestLog a WHERE requestid=" + requestid + " and a.logtype in ('0','2','3','t') and a.nodeid=" + nodeid + " AND a.logid NOT IN (SELECT MAX(b.logid) FROM workflow_requestlog b WHERE a.requestid=b.requestid AND a.workflowid=b.workflowid AND a.nodeid=b.nodeid AND a.operatedate=b.operatedate AND a.operatetime=b.operatetime AND a.operator=b.operator AND a.logtype=b.logtype)";
                rs1.executeSql(c_sql);
                while (rs1.next()) {
                    logids.add(Util.getIntValue(rs1.getString(1)));
                }
            }
        }

        return logids;
    }

    public static ArrayList uniqLogs(ArrayList logs) {
        ArrayList tmpLogs = new ArrayList();
        ArrayList logIds = new ArrayList();
        for (int i = 0; i < logs.size(); i++) {
            Hashtable ht = (Hashtable) logs.get(i);
            int logid = -1;
            try {
//				System.out.println(ht.get("tmpLogId"));
                logid = Integer.parseInt((String) ht.get("tmpLogId"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (logIds.indexOf(logid) < 0) {
                tmpLogs.add(ht);
                logIds.add(logid);
            }
        }
        return tmpLogs;
    }

    /**
     * 删除签字意见中的来源
     */
    public static String removeRemarkSource(String remark) {
        if (remark != null) {
            remark = remark.replaceAll("来自[a-zA-Z]{3,10}客户端|来自[a-zA-Z]{3,10}手机版|来自企业微信|来自微信企业号", "");
            remark = remark.replaceAll("<br/><br/><span style='font-size:11px;color:#666;'></span>", "");
        } else
            remark = "";
        return remark;
    }

    public static void loadNodeCanViewNodeIds(int viewNodeId, int workflowid, List<String> canViewIds, int requestid) {
        loadNodeCanViewNodeIds(viewNodeId, workflowid, canViewIds, requestid, false);
    }

    /**
     * 获取节点设置可查看意见范围
     *
     * @param viewNodeId
     * @param workflowid
     * @param canViewIds
     */
    public static void loadNodeCanViewNodeIds(int viewNodeId, int workflowid, List<String> canViewIds, int requestid, boolean isViewAllNodeLog) {
        RecordSet rs = new RecordSet();
        String singleViewLogIds = "";
        if (isViewAllNodeLog) {
            singleViewLogIds = "-1";
        } else {
            rs.executeQuery("select viewnodeids from workflow_flownode where workflowid= ?  and nodeid= ? ",workflowid,viewNodeId);
            if (rs.next()) {
                singleViewLogIds = rs.getString("viewnodeids");
            }
        }
        if ("-1".equals(singleViewLogIds)) {// 全部查看
            rs.executeSql("select nodeid from workflow_flownode where workflowid= " + workflowid + " and exists(select 1 from workflow_nodebase where id=workflow_flownode.nodeid and (requestid is null or requestid  = " + requestid + "))");
            while (rs.next()) {
                String tempNodeId = rs.getString("nodeid");
                if (!canViewIds.contains(tempNodeId)) {
                    canViewIds.add(tempNodeId);
                }
            }
        } else if (singleViewLogIds == null || "".equals(singleViewLogIds)) {// 全部不能查看
        } else {// 查看部分
            String tempidstrs[] = Util.TokenizerString2(singleViewLogIds, ",");
            for (int i = 0; i < tempidstrs.length; i++) {
                if (!canViewIds.contains(tempidstrs[i])) {
                    canViewIds.add(tempidstrs[i]);
                }
            }
        }
    }

    /**
     * 得到可查看的节点id
     *
     * @param requestid
     * @param workflowid
     * @return
     */
    public static String getViewLogIds(int requestid, int userid, int workflowid) {
        List<String> canViewIds = new ArrayList<String>();
        RecordSet recordSet = new RecordSet();
        //节点操作者
        recordSet.executeSql("select nodeid from workflow_currentoperator where requestid=" + requestid + " and userid=" + userid + " order by receivedate desc ,receivetime desc");
        if (recordSet.next()) {
            int viewnodeid = FreeNodeBiz.getExtendNodeId(requestid, Util.getIntValue(recordSet.getString("nodeid")));
            RequestLogCusBiz.loadNodeCanViewNodeIds(viewnodeid, workflowid, canViewIds, requestid);
        }
        //加载自由节点
        FreeNodeBiz.loadViewLogFreeNodeIds(requestid, canViewIds);
        return CollectionUtil.list2String(canViewIds, ",");
    }


    /**
     * 意见保存，返回requestlogId
     *
     * @param logEntity
     * @param user
     * @return
     */
    public static int saveRequestLog(RequestLogEntity logEntity, User user, boolean istest) {
        int logid = -1;
        if (logEntity == null) return logid;
        int operatorDept1 = user.getUserDepartment();
        int operatorSub = user.getUserSubCompany1();
        int operatorJob = Util.getIntValue(user.getJobtitle(), 0);
        String seclevel = Util.getIntValue(user.getSeclevel(), 0) + "";
        ConnStatement logstatement = null;
        String remarknew = logEntity.getRemark();
        RequestLogType logType = logEntity.getLogType();
        if (logType == RequestLogType.SAVE && !"".equals(Util.null2String(logEntity.getRemarkquote()))) {
            remarknew = logEntity.getRemarkquote();
        }
        logEntity.setRemarkquote("");
        logEntity.setOperator(user.getUID());
        logEntity.setOperatortype("1".equals(user.getLogintype()) ? 0 : 1);
        try {
            RecordSet rs = new RecordSet();
            boolean insertLog = true;
            if (logType == RequestLogType.SAVE) {
                String logsql = " SELECT logid FROM workflow_requestlog WHERE requestid= ? AND nodeid= ? AND logtype=? AND OPERATOR = ? AND operatortype = ?";
                rs.executeQuery(logsql, logEntity.getRequestid(), logEntity.getNodeid(), logType.getKey(), user.getUID(), logEntity.getOperatortype());
                if (rs.next()) {
                    logid = rs.getInt("logid");
                    insertLog = false;
                    String updatelogsql = " UPDATE workflow_requestlog SET operatedate= ?,operatetime= ?," +
                            " remark= ?, clientip= ?, destnodeid= ?, annexdocids= ?, " +
                            " requestLogId= ?, signdocids= ?, signworkflowids= ?, isMobile= ?," +
                            " SpeechAttachment= ?, HandWrittenSign= ?, remarkLocation=?,remarkquote=?,fulltextannotation = ?,speechAttachmente9 = ? where requestid=" + logEntity.getRequestid() +
                            " AND nodeid=" + logEntity.getNodeid() + " AND logtype='" + logType.getKey() + "' AND OPERATOR = " + user.getUID() +
                            " AND operatortype = " + logEntity.getOperatortype();
                    logstatement = new ConnStatement();
                    logstatement.setStatementSql(updatelogsql);
                    logstatement.setString(1, logEntity.getOperatedate());
                    logstatement.setString(2, logEntity.getOperatetime());
                    logstatement.setString(3, logEntity.getRemark());
                    logstatement.setString(4, logEntity.getClientip());
                    logstatement.setInt(5, logEntity.getDestnodeid());
                    logstatement.setString(6, logEntity.getAnnexdocids());
                    logstatement.setInt(7, logEntity.getRequestLogId());
                    logstatement.setString(8, logEntity.getSigndocids());
                    logstatement.setString(9, logEntity.getSignworkflowids());
                    logstatement.setString(10, logEntity.getIsMobile());
                    logstatement.setInt(11, logEntity.getSpeechAttachment());
                    logstatement.setString(12, String.valueOf(logEntity.getHandWrittenSign()));
                    logstatement.setString(13, logEntity.getRemarkLocation());
                    logstatement.setString(14, logEntity.getRemarkquote());
                    logstatement.setString(15, logEntity.getFulltextannotation());
                    logstatement.setString(16, logEntity.getSpeechAttachmente9());
                    logstatement.executeUpdate();
                }
            } else {
                String deletelogsql = " DELETE from workflow_requestlog WHERE requestid= ? AND nodeid= ? AND (logtype='1') AND OPERATOR = ? AND operatortype = ?";
                rs.executeUpdate(deletelogsql, logEntity.getRequestid(), logEntity.getNodeid(), user.getUID(), logEntity.getOperatortype());
            }
            //插入意見
            if (insertLog) {
                String uuid = UUID.randomUUID().toString();
                String insertlogsql = " INSERT INTO workflow_requestlog (requestid,workflowid,nodeid,logtype, operatedate, " +
                        " operatetime,OPERATOR, remark,clientip,operatortype,destnodeid,receivedPersons, " +
                        " agentorbyagentid,agenttype,showorder,annexdocids,requestLogId,operatorDept, " +
                        " signdocids,signworkflowids,isMobile,HandWrittenSign,SpeechAttachment,receivedPersonids,remarkLocation,remarkquote,fulltextannotation,speechAttachmente9,uuid,operatorSub, operatorJob, seclevel) " +
                        " VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ";
                logstatement = new ConnStatement();
                logstatement.setStatementSql(insertlogsql);
                logstatement.setInt(1, logEntity.getRequestid());
                logstatement.setInt(2, logEntity.getWorkflowid());
                logstatement.setInt(3, logEntity.getNodeid());
                logstatement.setString(4, logType.getKey());
                logstatement.setString(5, logEntity.getOperatedate());
                logstatement.setString(6, logEntity.getOperatetime());
                logstatement.setInt(7, user.getUID());
                logstatement.setString(8, remarknew);
                logstatement.setString(9, logEntity.getClientip());
                logstatement.setInt(10, logEntity.getOperatortype());
                logstatement.setInt(11, logEntity.getDestnodeid());
                logstatement.setString(12, logEntity.getReceivedPersons());
                logstatement.setInt(13, logEntity.getAgentorbyagentid());
                logstatement.setString(14, logEntity.getAgenttype());
                logstatement.setInt(15, logEntity.getShoworder());
                logstatement.setString(16, logEntity.getAnnexdocids());
                logstatement.setInt(17, logEntity.getRequestLogId());
                logstatement.setString(18, String.valueOf(operatorDept1));
                logstatement.setString(19, logEntity.getSigndocids());
                logstatement.setString(20, logEntity.getSignworkflowids());
                logstatement.setString(21, logEntity.getSignSource().getType());
                logstatement.setString(22, String.valueOf(logEntity.getHandWrittenSign()));
                logstatement.setInt(23, Util.getIntValue(logEntity.getSpeechAttachment(), 0));
                logstatement.setString(24, logEntity.getReceivedpersonids());
                logstatement.setString(25, logEntity.getRemarkLocation());
                logstatement.setString(26, logEntity.getRemarkquote());
                logstatement.setString(27, logEntity.getFulltextannotation());
                logstatement.setString(28, logEntity.getSpeechAttachmente9());
                logstatement.setString(29, uuid);
                logstatement.setInt(30, operatorSub);
                logstatement.setInt(31, operatorJob);
                logstatement.setString(32, seclevel);
                logstatement.executeUpdate();
                logstatement.close();

                rs.executeQuery("select logid from workflow_requestlog where requestid  = ? and uuid = ?", logEntity.getRequestid(), uuid);
                if (rs.next()) {
                    logid = rs.getInt("logid");
                }
            }

            /**
             * 处理签字意见的权限,督办(s)所有人都有权限，其他的都只给日志的操作人赋予权限
             * 处理日志查看权限
             */
            if (logType != RequestLogType.SAVE) {
                rs.executeQuery("select currentnodeid,currentnodetype from workflow_requestbase where requestid = ?", logEntity.getRequestid());
                int curnodeid = 0;
                int curnodetype = -1;
                if (rs.next()) {
                    curnodeid = rs.getInt("currentnodeid");
                    curnodetype = rs.getInt("currentnodetype");
                }
                NodeInfoEntity nodeInfoEntity = WorkflowBaseBiz.getNodeInfo(curnodeid);
                Set<String> branchNodeSet = new HashSet<String>();
                if ("2".equals(nodeInfoEntity.getNodeAttribute())) {   //分支中间节点
                    WFLinkInfo wflinkinfo = new WFLinkInfo();
                    String branchnodes = wflinkinfo.getNowNodeids(logEntity.getRequestid());
                    if (!"".equals(branchnodes)) {
                        String[] strs = branchnodes.split(",");
                        for (int k = 0; k < strs.length; k++) {
                            String nodestr = strs[k];
                            if (!"-1".equals(nodestr)) {
                                branchNodeSet.add(nodestr);
                            }
                        }
                    }
                }

                //流程的非归档节点，且插入日志的节点仍然是流程的当前节点，则需要日志权限控制
                if (!"3".equals(curnodetype) && (curnodeid == logEntity.getNodeid() || branchNodeSet.contains(String.valueOf(logEntity.getNodeid())))) {
                    int loguserid = user.getUID();
                    if (logType == RequestLogType.SUPERVISE) { // 督办所有人有权限
                        loguserid = -1;
                    }
                    String rightSql = "insert into workflow_logviewusers (logid,userid) values (? , ?)";
                    rs.executeUpdate(rightSql, logid, loguserid);
                }

                RequestSignRelevanceWithMe reqsignwm = new RequestSignRelevanceWithMe();
                reqsignwm.inertRelevanceInfo(String.valueOf(logEntity.getWorkflowid()), String.valueOf(logEntity.getRequestid()), String.valueOf(logEntity.getNodeid()),
                        logType.getKey(), logEntity.getOperatedate(), logEntity.getOperatetime(), String.valueOf(user.getUID()), remarknew);

                //提醒
                List<String> atResourceids = reqsignwm.parseRemark(remarknew);
                if (atResourceids.size() > 0) {
                    RequestOperationMsgManager romm = new RequestOperationMsgManager();
                    romm.remarkAtMsg(String.valueOf(logEntity.getRequestid()), String.valueOf(user.getUID()), atResourceids);
                }
            }
        } catch (Exception e) {
            log.info(new StringBuilder().append("~requestlog~rstlogpara:").append(JSONObject.toJSONString(logEntity)).append(",remark:").append(remarknew).toString());
            e.printStackTrace();
        } finally {
            if (logstatement != null) logstatement.close();
        }
        return logid;
    }


    /**
     * 根据来源获取需要自定义拼接的条件
     * @return
     */
    public static String getCustomSourceCondition(String source,Map<String,Object> params){
        String result = "";
        if("wfCenter".equals(source)){
            if(!"".equals(Util.null2String(params.get("logids")))){
                result += " and logid in(" + Util.null2String(params.get("logids")) + ") ";
            }
        }
        return result;
    }
}
