package com.seeyon.apps.src_flowIntegration.listener;

import cn.hutool.log.Log;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.addressbook.manager.AddressBookCustomerFieldInfoManager;
import com.seeyon.apps.addressbook.po.AddressBook;
import com.seeyon.apps.common.config.ICstConfigApi;
import com.seeyon.apps.common.plugin.vo.ConfigVo;
import com.seeyon.apps.extIntegration.vo.ExtAffair;
import com.seeyon.apps.extIntegration.vo.ExtSummary;
import com.seeyon.apps.src_flowIntegration.config.FlowIntegrationConfigProvider;
import com.seeyon.apps.src_flowIntegration.constants.FlowIntegrationConstants;
import com.seeyon.apps.src_flowIntegration.dao.SrcFlowDao;
import com.seeyon.apps.src_flowIntegration.util.*;
import com.seeyon.apps.zhifei.event.ExtIntegrationExtendEvent;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.ctpenumnew.manager.EnumManager;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.ctp.util.annotation.ListenEvent;
import com.seeyon.utils.http.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import www.seeyon.com.utils.StringUtil;
import www.seeyon.com.utils.UUIDUtil;

import javax.inject.Inject;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class FlowEventListener {

    private static Log log = Log.get(FlowEventListener.class);

    protected ICstConfigApi cstConfigApi = (ICstConfigApi) AppContext.getBean("cstConfigApi");
    @Autowired
    private FlowIntegrationConfigProvider configProvider;
    @Inject
    private OrgManager orgManager;
    @Inject
    private AddressBookCustomerFieldInfoManager addressBookCustomerFieldInfoManager;
    @Inject
    private SrcFlowDao srcFlowDao;
    @Inject
    private EnumManager enumManagerNew;

    public ConfigVo getFlowConfig() {
        return this.cstConfigApi.getConfig(this.getPluginId());
    }

    public String getPluginId() {
        return FlowIntegrationConstants.getPluginId();
    }



    /**编写一个事件监听ExtIntegrationExtendEvent**/
    /**
     * 流程待办事件
     * @param event
     * @throws BusinessException
     */
    @ListenEvent(event = ExtIntegrationExtendEvent.class, async = true)
    public void onExtIntegrationEvent(ExtIntegrationExtendEvent event){
        System.out.println("统一待办集成监听");
        ConfigVo configVo = this.getFlowConfig();
//        创建最终推送返回对象
        JSONObject jsonObject = new JSONObject();
        try {
//            判断当前流程是否需要进行流程审批状态返回
            ExtSummary extSummary = event.getExtSummary();
//            获取summaryId
            String summaryId = extSummary.getExtSummaryId();
//              获取系统内置参数第三方系统主数据字段信息
            String extAttrLabel = configProvider.getBizConfigByKey(FlowIntegrationConstants.extAttrLabel);
//            根据summaryId获取colSummary对象//优化点通过ID查询ColSummary对象
//                                 发起人      流程ID    模板ID        表单数据ID      表单ID    表单应用ID
//            id,state,subject,start_member_id,process_id,templete_id,form_recordid,formid,form_appid
            Map summaryMap = srcFlowDao.getColSummaryById(summaryId);
//            获取流程逻辑数据，获取流程表单字段对象。
            String formAppid = summaryMap.get("form_appid")==null?"":summaryMap.get("form_appid").toString();
            String fieldInfo = srcFlowDao.getFieldInfoByFormId(formAppid);
            JSONObject fieldjson = JSONObject.parseObject(fieldInfo);
//            获取表单信息，制定唯一值信息，第三方系统编码信息
            JSONObject frontFormmain = fieldjson.getJSONObject("front_formmain");
            String tableName = frontFormmain.getString("tableName");
            String tirdFlowIdName = FieldUtil.isDisplayExists(frontFormmain,"第三方系统流程ID");
            if(StringUtil.isEmpty(tirdFlowIdName)){
                log.info("当前表单中不存在集成指定字段。不进行流程状态回传。");
                return ;
            }
            String processId = summaryMap.get("process_id")==null?"":summaryMap.get("process_id").toString();
//            id,process_id,action_user_id,action_time,action_desc，审批记录
            List<Map<String ,String>> processLogs = srcFlowDao.getProcessLogsByProcessId(processId);
//            创建审批记录对象
            JSONArray completedList = new JSONArray();
            for(Map<String,String> processLog :processLogs){
//                创建参数对象转换参数信息
                JSONObject completed = new JSONObject();
//                处理节点名称（当前功能无法获取，暂时为空）
                completed.put("affairName","");
//                处理人信息
                completed.put("affairMember","");
                completed.put("affairMemberLoginName","");
                completed.put("affairMemberthirdPartyLoginName","");
                String actionUserId = processLog.get("actionUserId");
                if(StringUtil.isNotEmpty(actionUserId)){
                    V3xOrgMember v3xOrgMember = orgManager.getMemberById(Long.parseLong(actionUserId));
                    AddressBook memberAddressBook = addressBookCustomerFieldInfoManager.getByMemberId(v3xOrgMember.getId());
                    if(null == memberAddressBook) {
                        log.info("人员自定义数据未维护，无法单点登录！");
                        return;
                    }
                    JSONObject addressBookjson = AddressBookUtil.appleAddressBook(memberAddressBook,enumManagerNew);
//                    通过字段名称查询人员账号主数据数据库字段
                    String extAttrName = srcFlowDao.getMetadataNameByLabel(extAttrLabel);
                    String extAttrValue = addressBookjson.getString(extAttrName);
                    log.info("查询对应人员账号"+extAttrValue);
                    if(StringUtil.isEmpty(extAttrValue)){
                        log.info(extAttrLabel+"未维护，无法单点登录！");
                        return;
                    }
                    completed.put("affairMember",v3xOrgMember.getName());
                    completed.put("affairMemberLoginName",v3xOrgMember.getLoginName());
                    completed.put("affairMemberthirdPartyLoginName",extAttrValue);
                }
//                处理事项状态及描述
                String actionId = processLog.get("actionId");
//                处理操作状态字段转换成对应状态
                completed.put("affairStatus",TransitionAffairUtil.actionIdTransitionAffairStatus(actionId));
                completed.put("affairStatusTxt",TransitionAffairUtil.actionIdTransitionAffairStatusTxt(actionId));
//                处理时间
                completed.put("completeTime",processLog.get("actionTime"));
//                是否最新处理，当前为处理日志，默认为flase
                completed.put("isLatest",false);
                completedList.add(completed);
            }
//            解析当前审批信息
//            添加当前审批信息到completedList对象中
            List<ExtAffair> extAffairs = extSummary.getExtAffairs();
            System.out.println(extAffairs.size());
            for(ExtAffair extAffair : extAffairs){
                log.info("当前节点状态为" + extAffair.getCtpAffairState());
                log.info("当前节点副状态为" + extAffair.getCtpAffairSubState());
//                主状态为已发、已办、撤销、回退、取回、终止,状态为审批，进行数据处理
                if(isCtpAffairState(extAffair.getCtpAffairState())){
                    JSONObject completed = new JSONObject();
//                    节点名称暂无法获取到位空
                    completed.put("affairName","");
                    long ctpAffairMemberId = extAffair.getCtpAffairMemberId();
                    V3xOrgMember v3xOrgMember = orgManager.getMemberById(ctpAffairMemberId);
                    AddressBook memberAddressBook = addressBookCustomerFieldInfoManager.getByMemberId(v3xOrgMember.getId());
                    if(null == memberAddressBook) {
                        log.info("人员自定义数据未维护，无法单点登录！");
                        return;
                    }
                    JSONObject addressBookjson = AddressBookUtil.appleAddressBook(memberAddressBook,enumManagerNew);
//                    通过字段名称查询人员账号主数据数据库字段
                    String extAttrName = srcFlowDao.getMetadataNameByLabel(extAttrLabel);
                    String extAttrValue = addressBookjson.getString(extAttrName);
                    log.info("查询对应人员账号"+extAttrValue);
                    if(StringUtil.isEmpty(extAttrValue)){
                        log.info(extAttrLabel+"未维护，无法单点登录！");
                        return;
                    }
                    completed.put("affairMember",v3xOrgMember.getName());
                    completed.put("affairMemberLoginName",v3xOrgMember.getLoginName());
                    completed.put("affairMemberthirdPartyLoginName",extAttrValue);
//                    处理操作状态字段转换成对应状态
                    completed.put("affairStatus",TransitionAffairUtil.extAffairAffairStatus(extAffair));
                    completed.put("affairStatusTxt",TransitionAffairUtil.extAffairAffairStatusTxt(extAffair));
//                    处理时间
                    System.out.println(extAffair.getCtpAffairCompleteDate());
                    completed.put("completeTime", TimestampConverter.timestampToDateTime(extAffair.getCtpAffairCompleteDate()));
//                    是否最新处理，当前为处理日志，默认为flase
                    completed.put("isLatest",true);
                    completedList.add(completed);
//                    只对收个结果进行返回，参数处理完成则跳出当前循环
                    break;
                }else{
                    continue;
                }
            }
//            保存流程处理信息
            jsonObject.put("completedList",completedList);

            String thirdpartyCodeName = FieldUtil.isDisplayExists(frontFormmain,"第三方系统标识");
            String flowStatusCallbackUrlName = FieldUtil.isDisplayExists(frontFormmain,"流程审核状态回调地址");
//            获取表单数据ID
            String formRecordid = summaryMap.get("form_recordid")==null?"":summaryMap.get("form_recordid").toString();
//            设置表单查询字段
            String[] fieldNames = {tirdFlowIdName,thirdpartyCodeName,flowStatusCallbackUrlName};
//            设置表单查询字段及结果
            Map<String,String> whereParam = new HashMap<>();
            whereParam.put("id",formRecordid);
//            通过formmian表单及数据ID获取当前表单中的第三方系统唯一值字段
            List<Map<String,Object>> formmainDatas = srcFlowDao.getFormDataByParam(tableName,fieldNames,whereParam);
            if(formmainDatas.size()!=1){
                log.info("当前查询结果不唯一，请检查");
                return;
            }
//            封装第三方系统流程唯一值字段
            Map<String,Object> map = formmainDatas.get(0);
            String tirdFlowId,flowStatusCallbackUrl,thirdpartyCode;
            if(map.size()>0){
                tirdFlowId = formmainDatas.get(0).get(tirdFlowIdName)==null?"":formmainDatas.get(0).get(tirdFlowIdName).toString();
                flowStatusCallbackUrl = formmainDatas.get(0).get(flowStatusCallbackUrlName)==null?"":formmainDatas.get(0).get(flowStatusCallbackUrlName).toString();
                thirdpartyCode = formmainDatas.get(0).get(thirdpartyCodeName)==null?"":formmainDatas.get(0).get(thirdpartyCodeName).toString();
            }else{
                tirdFlowId = "";
                flowStatusCallbackUrl = "";
                thirdpartyCode = "";
            }
//            保存第三方流程ID数据
            jsonObject.put("thirdFlowId",tirdFlowId);
//            设置当前待办审批列表，当前为审批触发不添加待办信息
            jsonObject.put("todoList",new JSONArray());
//            设置的当前流程表单字段信息，此为流程审批过程回调不添加表单数据
            jsonObject.put("formInfo",new JSONObject());
            System.out.println(jsonObject);
//            进行请求参数加密
            String paramValue = srcFlowDao.getThirdpartyParamByThirdpartyCode(thirdpartyCode);
            JSONObject paramjson = JSONObject.parseObject(paramValue);
            String secretKey = paramjson.getString("secretKey");
            String vi = paramjson.getString("vi");
            String datastr = jsonObject.toString();
//            加密请求参数
            String encrypted = AesUtil.encrypt(datastr,secretKey,vi);
            long timestamp = new Date().getTime();
//            生成随机数
            String nonce = UUIDUtil.getUUIDLong()+"";
            String signContent = encrypted + timestamp + nonce + secretKey;
            String sign = SignUtil.sha256(signContent);
            JSONObject param = new JSONObject();
            param.put("data",encrypted);
            param.put("timestamp",timestamp+"");
            param.put("nonce",nonce);
            param.put("sign",sign);
//            调通接口推送数据到第三方系统
            String res = HttpClient.httpPostRaw(flowStatusCallbackUrl,param.toString(),new HashMap<String,String>(), null);
            JSONObject 	resultJSON = JSONObject.parseObject(res);
            String code = resultJSON.getString("code");
            if("0".equals(code)){
                log.info("推送结果成功");
            }else{
                log.info("推送结果失败");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private boolean isCtpAffairState(int ctpAffairState){
        if(ctpAffairState ==2 || ctpAffairState == 4 || ctpAffairState == 5 || ctpAffairState == 6 || ctpAffairState == 7 ||
                ctpAffairState == 8 || ctpAffairState == 11 || ctpAffairState ==15){
            return true;
        }
        return false;
    }

}
