package org.springblade.flow.engine.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.springblade.flow.base.ActionResult;
import org.springblade.flow.base.util.ActivitiNativeTaskQueryUtils;
import org.springblade.flow.base.util.ActivitiUtils;
import org.springblade.flow.base.util.IdWorker;
import org.springblade.flow.base.vo.PageListVO;
import org.springblade.flow.base.vo.PaginationVO;
import org.springblade.flow.engine.custom.constants.GlobalProcessVariableConstants;
import org.springblade.flow.engine.entity.FlowTaskNotificationEntity;
import org.springblade.flow.engine.enums.FlowMessageEnum;
import org.springblade.flow.engine.model.FlowHandleModel;
import org.springblade.flow.engine.model.flowengine.FlowModel;
import org.springblade.flow.engine.model.flowlaunch.FlowLaunchListVO;
import org.springblade.flow.engine.model.flowtask.PaginationFlowTask;
import org.springblade.flow.engine.service.FlowTaskNewService;
import org.springblade.flow.engine.service.FlowTaskNotificationService;
import org.springblade.flow.engine.service.FlowTaskService;
import org.springblade.flow.exception.WorkFlowException;
import org.springblade.flow.message.service.MessageService;
import org.springblade.flow.util.JsonUtil;
import org.springblade.flow.util.JsonUtilEx;
import org.springblade.flow.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.hutool.core.collection.CollectionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * 流程发起
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Api(tags = "流程发起", value = "FlowLaunch")
@RestController
@RequestMapping("/paas/workflow/Engine/FlowLaunch")
public class FlowLaunchController {

	@Autowired
	private FlowTaskService flowTaskService;
	@Autowired
	private MessageService messageService;
	@Autowired
	private FlowTaskNewService flowTaskNewService;

	@Resource
	private HistoryService historyService;
	@Resource
	private UserProvider userProvider;
	@Resource
	private RuntimeService runtimeService;
	@Resource
	private ActivitiUtils activitiUtils;
	@Resource
	private TaskService taskService;
	@Resource
	private ActivitiNativeTaskQueryUtils activitiNativeTaskQueryUtils;
	@Resource
	private IdWorker idWorker;
	@Resource
	private FlowTaskNotificationService flowTaskNotificationService;

	/**
	 * 获取流程发起列表
	 *
	 * @param paginationFlowTask
	 * @return
	 */
	// 接口已经测试
	@Transactional(readOnly = true)
	@ApiOperation("获取流程发起列表(带分页)")
	@GetMapping
	public ActionResult<PageListVO<FlowLaunchListVO>> list(PaginationFlowTask paginationFlowTask) {
		try {
			List<FlowLaunchListVO> listVO = flowTaskService.getLaunchList(paginationFlowTask);
			PaginationVO paginationVO = JsonUtil.getJsonToBean(paginationFlowTask, PaginationVO.class);
			return ActionResult.page(listVO, paginationVO);
		} catch (Exception e) {
			e.printStackTrace();
			return ActionResult.fail("查询失败");
		}
	}

	/**
	 * 删除流程发起
	 *
	 * @param id 主键值
	 * @return
	 */
	// 接口已经测试
	@ApiOperation("删除流程发起")
	@DeleteMapping("/{id}")
	public ActionResult delete(@PathVariable("id") String id) throws WorkFlowException {
		try {
			long count = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(id).count();
			HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
					.processInstanceBusinessKey(id).singleResult();
			if (count != 0) {
//                return ActionResult.fail("流程正在运行,无法删除!");
				flowTaskService.delete(historicProcessInstance.getId(), false);
				return ActionResult.success("删除成功");
			} else {
				flowTaskService.delete(historicProcessInstance.getId(), true);
				return ActionResult.success("删除成功");
			}
		} catch (Exception e) {
			e.printStackTrace();
			return ActionResult.fail("删除失败");
		}

//        FlowTaskEntity entity = flowTaskService.getInfo(id);
//        if (entity != null) {
//            if (entity.getFlowType() == 1) {
//                return ActionResult.fail("功能流程不能删除");
//            }
//            if (!FlowNature.ParentId.equals(entity.getParentId()) && StringUtil.isNotEmpty(entity.getParentId())) {
//                return ActionResult.fail("子表数据不能删除");
//            }
//            flowTaskService.delete(entity);
//            return ActionResult.success("删除成功");
//        }
	}

	/**
	 * 待我审核催办
	 *
	 * @param id 主键值
	 * @return
	 */
	@ApiOperation("发起催办")
	@PostMapping("/Press/{id}")
	public ActionResult press(@PathVariable("id") String id) throws WorkFlowException {
		try {
//            FlowTaskEntity flowTaskEntity = flowTaskService.getInfo(id);

			ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(id)
					.singleResult();
			if (processInstance == null) {
				return ActionResult.fail("流程已经结束,不可以进行催办");
			}
			String processInstanceId = processInstance.getProcessInstanceId();
			List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);
			activeActivityIds = CollectionUtil.distinct(activeActivityIds);

			List<Task> tasks = activitiNativeTaskQueryUtils
					.getTasksByProcessInstanceIdAndTaskDefinitionKey(processInstanceId, activeActivityIds);
			List<String> userIdSet = new ArrayList<>();

			List<FlowTaskNotificationEntity> flowTaskNotificationEntityList = new ArrayList<>();
			for (Task task : tasks) {
				List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(task.getId());
				for (IdentityLink identityLink : identityLinksForTask) {
					String userId = identityLink.getUserId();
					userIdSet.add(userId);
				}
				userIdSet = CollectionUtil.distinct(userIdSet);

				FlowTaskNotificationEntity flowTaskNotificationEntity = new FlowTaskNotificationEntity();
				flowTaskNotificationEntity.setId(idWorker.nextId() + "");
				flowTaskNotificationEntity.setTaskId(task.getId());
				flowTaskNotificationEntity.setTaskName(task.getName());
				flowTaskNotificationEntity.setTaskAssignee(task.getAssignee());
				flowTaskNotificationEntity.setProcessInstanceId(processInstanceId);
				flowTaskNotificationEntity.setProcessInstanceName(processInstance.getName());
				flowTaskNotificationEntity.setOpTime(new Date());
				flowTaskNotificationEntity.setNotifyType("1");
				flowTaskNotificationEntity.setRemarks(processInstance.getName() + "【催办】");
				flowTaskNotificationEntity.setCreateBy(userProvider.getUserId());
				flowTaskNotificationEntity.setCreateTime(new Date());
				flowTaskNotificationEntityList.add(flowTaskNotificationEntity);
			}

			if (CollectionUtil.isEmpty(userIdSet)) {
				return ActionResult.fail("未找到催办人");
			} else {
				// 设置催办标识
				runtimeService.setVariable(processInstanceId, GlobalProcessVariableConstants.NOTIFICATION_FLAG,
						Boolean.TRUE);
				flowTaskNotificationService.saveBatch(flowTaskNotificationEntityList);
				Map<String, Object> message = new HashMap<>(16);
				message.put("type", FlowMessageEnum.wait.getCode());
				message.put("id", processInstance.getId());
				String bodyText = JsonUtilEx.getObjectToString(message);
				messageService.sentMessage(userIdSet, processInstance.getName() + "【催办】", bodyText);
				return ActionResult.success("催办成功");
			}

		} catch (Exception e) {
			e.printStackTrace();
			return ActionResult.fail("催办失败");
		}
	}

	/**
	 * 撤回流程发起
	 * 注意：在撤销流程时要保证你的下一节点没有处理这条记录；如已处理则无法撤销流程。
	 *
	 * @param id              主键值
	 * @param flowHandleModel 经办记录
	 * @return
	 */
	@ApiOperation("撤回流程发起")
	@PutMapping("/{id}/Actions/Withdraw")
	public ActionResult revoke(@PathVariable("id") String id, @RequestBody FlowHandleModel flowHandleModel)
			throws WorkFlowException {
//        FlowTaskEntity flowTaskEntity = flowTaskService.getInfo(id);
		try {
			FlowModel flowModel = JsonUtil.getJsonToBean(flowHandleModel, FlowModel.class);
			ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(id)
					.singleResult();
			if (processInstance == null) {
				return ActionResult.fail("流程已经结束,无法撤回!");
			}
			String processDefinitionKey = processInstance.getProcessDefinitionKey();
			flowTaskNewService.revoke(processInstance, flowModel);
			return ActionResult.success("撤回成功");
		} catch (WorkFlowException e) {
			return ActionResult.fail(e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			return ActionResult.fail("撤回失败");
		}
	}
}
