package com.tofly.flow.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.api.message.MessageClient;
import com.tofly.api.message.MessageStateClient;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.log.annotation.ToFlyAppLog;

import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.flow.config.BuinessRouter;
import com.tofly.flow.dto.ProcessInfoDto;
import com.tofly.flow.dto.ProcessInstanceDto;
import com.tofly.flow.dto.ProcessNodeInfoDto;
import com.tofly.flow.dto.ProcessTemplateNodeInfoDto;
import com.tofly.flow.entity.FormData;
import com.tofly.flow.entity.FormInstance;
import com.tofly.flow.entity.ProcessApprovalHistory;
import com.tofly.flow.entity.ProcessInstance;
import com.tofly.flow.entity.ProcessInstanceNodeInfo;
import com.tofly.flow.entity.ProcessTemplate;
import com.tofly.flow.entity.ProcessTemplateNode;
import com.tofly.flow.service.FormDataService;
import com.tofly.flow.service.FormInstanceService;
import com.tofly.flow.service.ProcessApprovalHistoryService;
import com.tofly.flow.service.ProcessInstanceNodeInfoService;
import com.tofly.flow.service.ProcessInstanceService;
import com.tofly.flow.service.ProcessTemplateNodeService;
import com.tofly.flow.service.ProcessTemplateService;
import com.tofly.flow.vo.ApprovalNodeInfoVo;
import com.tofly.pojo.message.Messagepush;
import com.tofly.pojo.message.Messagerecipient;

import lombok.AllArgsConstructor;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;


import java.util.*;

/**
 * 流程表单接口
 *
 * @author zhoux
 */
@RestController
@AllArgsConstructor
@RequestMapping("/process")
@Api(tags="流程表单管理接口")
public class ProcessController {

    private final  ProcessInstanceService processInstanceService;
    
    private final  ProcessInstanceNodeInfoService  processInstanceNodeInfoService;
    
    private final  FormInstanceService formInstanceService;
     
    private final  ProcessTemplateService processTemplateService;
    
    private final  ProcessTemplateNodeService processTemplateNodeService;
    
    private final  ProcessApprovalHistoryService processApprovalHistoryService;
        
    private final  MessageClient messageClient;
    
    private final  MessageStateClient messageStateClient;
    
    
    /**
    * 流程节点配置审批信息
    * @param processInstanceNodeInfo
    */
    @PostMapping("/configTemplateNode")
    @ApiOperation(value = "流程节点配置审批信息 1、审批人（approvalPersonId）2、审批人姓名（approvalPersonName）"
    		+ "3、流程模板ID(processTemplateId) 4 流程节点名称(nodeAlias) 5、流程节点序号（nodeSortNum） ")
    public ResultRespone configTemplateNode(@RequestBody ProcessTemplateNodeInfoDto processTemplateNodeInfoDto) {
    	
    	try {
    		
    		Map<String,String> returnMap = processTemplateNodeService.configTemplateNode(processTemplateNodeInfoDto);
    		
    		if(returnMap.get("flag").equals("true")) {
    			return ResultRespone.success(returnMap.get("msg"));
    		}else {
    			return ResultRespone.failed(returnMap.get("msg"));
    		}    		    		
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
		}
    }
    
    
    
    
    /**
     * 流程审批
     * @param processInstanceNodeInfo
     */
    @PostMapping("/approvalInstance" )
    @ApiOperation(value = "审批流程节点")
    public ResultRespone approvalInstance(@RequestBody ApprovalNodeInfoVo approvalNodeInfoVo) {
    	
    	try {  		
    		ProcessInstance processInstance= processInstanceService.getById(approvalNodeInfoVo.getProcessId());    
    		
    		if(processInstance.getProcessStatus()==1) {
    			throw new Exception("该流程节点未完全配置，请检查。");
    		}else if(processInstance.getProcessStatus()==3){
    			throw new Exception("该流程已被拒绝，请重新发起流程。");
    		}else if(processInstance.getProcessStatus()==4){
    			throw new Exception("该流程已完成，请勿重复提交。");
    		}
    		Map<String,String> returnMap = processInstanceNodeInfoService.processApproval(approvalNodeInfoVo);
    		//是否消息通知
    		if(approvalNodeInfoVo.getIsMessagePush() == 1) {
    			ProcessTemplate processTemplate = processTemplateService.getById(processInstance.getProcessTemplateId());    			
    			//判断当前流程节点是否小于流程节点个数
    			if(approvalNodeInfoVo.getNodeSortNum()<processTemplate.getProcessNodesNum()) {
    				Messagepush messagepush = new Messagepush(); 
    				messagepush.setTopic(processTemplate.getProcessTemplateName()+"消息通知");			 
        			messagepush.setMessage(approvalNodeInfoVo.getApprovalSuggest());
        			messagepush.setCreateTime(new Date());
        			messagepush.setCreateUser(SecurityUtils.getUserId());
        			messagepush.setType("13");    			
        			messagepush.setTableName("TF_YWPN_APPLY_INSTALL");
        			messagepush.setTableId(approvalNodeInfoVo.getBuinessInfoId());
        				
       			 	Messagerecipient messagerecipient = new Messagerecipient();
        			if(approvalNodeInfoVo.getApprovalStatus()==1) {
        				
        				ProcessInstanceNodeInfo pini = processInstanceNodeInfoService.getOne(Wrappers.<ProcessInstanceNodeInfo>lambdaQuery()
                				.eq(ProcessInstanceNodeInfo::getProcessId,processInstance.getId())
                    			.eq(ProcessInstanceNodeInfo::getNodeSortNum,approvalNodeInfoVo.getNodeSortNum()+1));
        				
            	        messagerecipient.setRecipient(pini.getApprovalPersonId());
            	        messagepush.setRouteIp(BuinessRouter.INSTALL_ROUTER.get(approvalNodeInfoVo.getNodeSortNum()+1));
        			}else if(approvalNodeInfoVo.getApprovalStatus()==2) {	
        				
        				ProcessInstanceNodeInfo pini =processInstanceNodeInfoService.getOne(Wrappers.<ProcessInstanceNodeInfo>lambdaQuery()
                				.eq(ProcessInstanceNodeInfo::getProcessId,processInstance.getId())
                    			.eq(ProcessInstanceNodeInfo::getNodeSortNum,approvalNodeInfoVo.getNodeSortNum()-1));
        				
        				messagerecipient.setRecipient(pini.getApprovalPersonId());
        				messagepush.setRouteIp(BuinessRouter.INSTALL_ROUTER.get(approvalNodeInfoVo.getNodeSortNum()-1));
        			}
        			
        			//messageClient.save(messagepush);
         	        messagerecipient.setMessageId(messagepush.getId());    	
        			messagerecipient.setFlag("0");
        	       // messageStateClient.save(messagerecipient);
    			}
    			
    		}
    		
    		if(returnMap.get("flag").equals("true")) {
    			return ResultRespone.success(returnMap.get("msg"));
    		}else {
    			return ResultRespone.failed(returnMap.get("msg"));
    		}  
    		
    		
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
		}
    }
    
    

    

    /**
     * 根据流程实例ID获取所有的流程节点审批信息
     * @param processInstanceId
     * @return ResultRespone
     */
    @ApiOperation(value = "根据流程实例ID获取所有的流程以及节点审批信息")
    @GetMapping("/processInstance/{id}")
    public ResultRespone queryProcessInstance(@PathVariable("id") Long processInstanceId) {
    	
    	try {
    		ProcessInfoDto instaceDto =new ProcessInfoDto();
        	ProcessInstance  processInstance =  processInstanceService.getById(processInstanceId);
        	BeanUtils.copyProperties(instaceDto,processInstance);
        	List<ProcessInstanceNodeInfo> nodeList= processInstanceNodeInfoService.list(Wrappers.<ProcessInstanceNodeInfo>lambdaQuery()
    				.eq(ProcessInstanceNodeInfo::getProcessId,processInstanceId)
    				.orderByAsc(ProcessInstanceNodeInfo::getNodeSortNum));
        	instaceDto.setProcessNodeInfos(nodeList);    	 
        	return ResultRespone.success(instaceDto);
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
		}
    }

    /**
     * 根据流程节点信息获取表单信息
     * @param processInstanceId
     * @param ProcessInstanceAlias
     * @return ResultRespone
     */
    @ApiOperation(value = "根据流程节点信息获取表单信息以及表单数据")
    @GetMapping("/queryNodeInfos")
    public ResultRespone queryNodeInfos(@RequestParam(value = "processInstanceId",required = true) String processInstanceId, 
    		@RequestParam(value = "processInstanceNodeAlias",required = true) String processInstanceNodeAlias) {
    	
    	try {	
        	List<ProcessNodeInfoDto>  resList =new ArrayList<ProcessNodeInfoDto>();
        	List<ProcessInstanceNodeInfo> nodeList = processInstanceNodeInfoService.list(Wrappers.<ProcessInstanceNodeInfo>lambdaQuery()
    				.eq(ProcessInstanceNodeInfo::getProcessId,processInstanceId)
        			.eq(ProcessInstanceNodeInfo::getNodeAlias,processInstanceNodeAlias));
        	
        	for(ProcessInstanceNodeInfo node : nodeList) {
        		ProcessNodeInfoDto pnd= new ProcessNodeInfoDto();
        		BeanUtils.copyProperties(pnd,node);
        		pnd.setFormInfoDto(formInstanceService.getFormData(node.getFormId()));      
        		resList.add(pnd);
        	}
        	
        	return ResultRespone.success(resList);
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
		}
    }
    
    
    /**
     * 生成流程实例
     * @param id ProcessInstanceVo
     */
    @ApiOperation(value = "生成流程实例")
    @PostMapping("/newInstance")
    public ResultRespone newInstance(@RequestBody ProcessInstanceDto processInstanceDto) {
    	
    	try {
    		ProcessInstance pi =new ProcessInstance();
        	pi.setCreateTime(new Date());
        	pi.setCreateUser(SecurityUtils.getUserId());
        	pi.setCurrentNodeSort(1);
        	pi.setProcessDelFlag(1);
        	pi.setProcessInstanceName(processInstanceDto.getProcessInstanceName());
        	pi.setProcessTemplateId(processInstanceDto.getProcessTemplateId());
        	pi.setProcessStatus(1);       	
        	processInstanceService.save(pi);
        	
    		List<ProcessTemplateNode> nodes = processTemplateNodeService.list(Wrappers.<ProcessTemplateNode>lambdaQuery()
    				.eq(ProcessTemplateNode::getProcessTemplateId,processInstanceDto.getProcessTemplateId()));
    		
    		
    		for(ProcessTemplateNode node:nodes) {
    			ProcessInstanceNodeInfo nodeInfo =new ProcessInstanceNodeInfo();
    			
    			nodeInfo.setApprovalPersonId(node.getApprovalPersonId());
    			nodeInfo.setApprovalPersonName(node.getApprovalPersonName());
    			nodeInfo.setNodeAlias(node.getProcessNodeAlias());
    			nodeInfo.setProcessId(pi.getId());
    			nodeInfo.setNodeSortNum(node.getSortNum());
    			nodeInfo.setProcessNodeName(node.getProcessNodeName());
    			nodeInfo.setApprovalStatus(0);
    			
    			if(node.getFormTemplateId()!=0) {
    				FormInstance fi =new FormInstance();
    				fi.setFormTemplateId(node.getFormTemplateId());
    				formInstanceService.save(fi);
    				nodeInfo.setFormId(fi.getId());    				
    			}
    			    			
    			processInstanceNodeInfoService.save(nodeInfo);
    		}
        	return ResultRespone.success(pi);
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
    		
		}
    }
    
    
    /**
     * 流程实例启动
     * @param id ProcessInstanceVo
     */
    @ApiOperation(value = "流程实例启动")
    @PostMapping("/instanceRun/{id}")
    public ResultRespone instanceRun(@PathVariable("id") Long processInstanceId) {
    	
    	try {
    		  QueryWrapper<ProcessInstanceNodeInfo> query = new QueryWrapper<>();
	          query.select(" DISTINCT NODE_ALIAS,NODE_SORT_NUM ").lambda()
	          .eq(ProcessInstanceNodeInfo::getProcessId,processInstanceId).orderByAsc(ProcessInstanceNodeInfo::getNodeSortNum);
	          List<ProcessInstanceNodeInfo> processNodeList = processInstanceNodeInfoService.list(query);
	  		
	  		
	  	      ProcessInstance updateInstance =new ProcessInstance();				
	  		  updateInstance.setId(processInstanceId);
	  		  updateInstance.setProcessStatus(2);
	  		  if(processNodeList.size()==0) {
	  			  throw new Exception("该流程实例没有配置节点，请检查。");
	  		  }
	  		  updateInstance.setCurrentNode(processNodeList.get(0).getNodeAlias());
	  		  processInstanceService.updateById(updateInstance);
	  		  
	  		return ResultRespone.success("流程实例启动成功");
	  		
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
    		
		}
    }
    
    
    

    /**
     * 通过id批量删除
     * @param ids id
     * @return ResultRespone
     */
    @ToFlyAppLog(title="通过id批量删除" )
    @ApiOperation(value = "通过ID批量删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "批量删除，多个id以逗号隔开", required = true, dataType = "String")
    })
    @DeleteMapping("/deleteByIds" )
    public ResultRespone removeById(String ids) {
    	try {
    		List<String> list = Arrays.asList(ids.split(","));
        	ProcessInstance pi =new ProcessInstance();
        	
        	for(String id:list) {
        		pi.setProcessDelFlag(2);
        		pi.setId(Long.valueOf(id));
        		processInstanceService.updateById(pi);
        	}
        	return ResultRespone.success("删除成功");
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
		}    	       
    }
    
    /**
     * 获取所有流程模板列表信息
     * @return ResultRespone
     */
    @ApiOperation(value = "获取所有流程模板列表信息")
    @GetMapping("/queryProcessTemplateList")
    public ResultRespone queryProcessTemplateList() {    	
    	try {
        	List<ProcessTemplate> tempList= processTemplateService.list();
        	return ResultRespone.success(tempList);
    	}catch (Exception e) {
    		return ResultRespone.failed(e.getMessage());
		}
    }
    
    /**
     * 根据流程模板ID获取该流程下所有的流程模板节点信息
     * @return ResultRespone
     */
    @ApiOperation(value = "根据流程模板ID获取该流程下所有的流程模板节点信息 id:流程模板ID ")
    @GetMapping("/processTemplateNodes/{id}")
    public ResultRespone queryProcessTemplateNodes(@PathVariable("id") Long processTemplateId) {    	
    	try {
    		    		
    		List<ProcessTemplateNode> nodes = processTemplateNodeService.list(Wrappers.<ProcessTemplateNode>lambdaQuery()
    				.eq(ProcessTemplateNode::getProcessTemplateId,processTemplateId));
    		
        	return ResultRespone.success(nodes);
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
		}
    }
    
    
    /**
     * 查询流程节点审批历史
     * @return ResultRespone
     */
    @ApiOperation(value = "查询流程节点审批历史")
    @GetMapping("/processHistroy/{id}")
    public ResultRespone processHistroy(@PathVariable("id") Long processId) {    	
    	try {
    		List<ProcessApprovalHistory> nodes = processApprovalHistoryService.list(Wrappers.<ProcessApprovalHistory>lambdaQuery()
    				.eq(ProcessApprovalHistory::getProcessId,processId));    		
        	return ResultRespone.success(nodes);
    	}catch (Exception e) {
    		e.printStackTrace();
    		return ResultRespone.failed(e.getMessage());
		}
    }
    
    
    
    
    
}