package com.yeejoin.amos.boot.module.common.biz.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.yeejoin.amos.boot.module.common.api.dto.FailureAuditDto;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.workflow.feign.WorkflowFeignService;
import com.yeejoin.amos.boot.module.common.api.dto.FailureDetailsDto;
import com.yeejoin.amos.boot.module.common.api.entity.FailureAudit;
import com.yeejoin.amos.boot.module.common.api.entity.FailureDetails;
import com.yeejoin.amos.boot.module.common.api.enums.FailureStatuEnum;
import com.yeejoin.amos.boot.module.common.api.mapper.FailureDetailsMapper;
import com.yeejoin.amos.boot.module.common.api.service.IFailureAuditService;
import com.yeejoin.amos.boot.module.common.api.service.IFailureDetailsService;

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2021-08-04
 */
@Service
public class FailureDetailsServiceImpl extends BaseService<FailureDetailsDto, FailureDetails, FailureDetailsMapper>
		implements IFailureDetailsService {

	@Autowired
	SourceFileServiceImpl sourceFileServiceImpl;
	
	@Autowired
	WorkflowFeignService workflowFeignService;

	@Value("${failure.work.flow.processDefinitionKey}")
	private String processDefinitionKey;

	@Autowired
	FailureAuditServiceImpl failureAuditServiceImpl;

	@Autowired
	IFailureAuditService failureAuditService;

	public static String EMERGENCY_COMMAND = "应急指挥科";

	private final Logger logger = LoggerFactory.getLogger(FailureDetailsServiceImpl.class);

	/**
	 * 分页查询
	 */
	public Page<FailureDetailsDto> queryForFailureDetailsPage(Page<FailureDetailsDto> page,Long currentStatus) {
		return this.queryForPage(page, null, false,currentStatus);
	}

	/**
	 * 列表查询 示例
	 */
	public List<FailureDetailsDto> queryForFailureDetailsList() {
		return this.queryForList("", false);
	}

	/**
	 * 根据状态查询
	 */
	public List<FailureDetails> queryForFailureDetailsList(Long currentStatus) {
		QueryWrapper<FailureDetails> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("current_status", currentStatus).orderByDesc("submission_time");
		return baseMapper.selectList(queryWrapper);

	}

	/**
	 * 查询任务状态数量
	 */
	public Integer queryStatusCount(Long currentStatus) {
		QueryWrapper<FailureDetails> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("current_status", currentStatus);
		return baseMapper.selectCount(queryWrapper);
	}

	/**
	 * 发起故障保修单
	 * @throws Exception 
	 */
	@Transactional
	public Object savemodel(FailureDetailsDto failureDetailsDto, ReginParams userInfo) throws Exception {
		String businessKey = buildOrderNo();
		 JSONObject body = new JSONObject();
	      body.put("businessKey", businessKey);
	        body.put("processDefinitionKey", processDefinitionKey);
	        JSONObject jsonObject =	workflowFeignService.startByVariable(body);
		if (jsonObject == null) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			// return CommonResponseUtil.failure("启动流程失败");
		}
		JSONObject instance = jsonObject.getJSONObject("data");
		if (instance == null) {
			// return CommonResponseUtil.failure("无提交隐患权限");
		}
		failureDetailsDto.setCurrentStatus(FailureStatuEnum.WAITING_AUDIT.getCode());
		// 拿到流程processId
		failureDetailsDto.setProcessId(instance.getString("id"));
		FailureDetailsDto model = null;
		try {
			if (ObjectUtils.isNotEmpty(failureDetailsDto.getAttachment())) {
				sourceFileServiceImpl.saveSourceFile(failureDetailsDto.getSequenceNbr(),
						failureDetailsDto.getAttachment());
			}
			model = this.createWithModel(failureDetailsDto);
			FailureAuditDto failureAuditDto = new FailureAuditDto();
			failureAuditDto.setAuditor(model.getRecUserName());
			failureAuditDto.setFaultId(model.getSequenceNbr());
			failureAuditDto.setAuditOpinion("已发起");
			failureAuditServiceImpl.savemodel(failureAuditDto);
		} catch (Exception e) {
			logger.info("添加故障维修信息到数据库失败");
			return false;
			// return CommonResponseUtil.failure("添加失败");
		}
		if (ObjectUtils.isNotEmpty(model)) {
			excuteTask( instance.getString("id"), userInfo, null);
		}
		return true;
	}

	public boolean excuteTask( Long sequenceNbr, ReginParams userInfo,
			String condition) {
		HashMap<String, Object> conditionMap = new HashMap<String, Object>();
		conditionMap.put("condition", condition);
		 Map<String,Object> map= checkExcuteTaskAuthMap(sequenceNbr,userInfo);
		 try {
			 if(Boolean.parseBoolean(map.get("checkFlag").toString())) {
				 workflowFeignService.pickupAndCompleteTask(map.get("taskId").toString(), conditionMap);
			 }
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	public boolean excuteTask(String procressId,  ReginParams userInfo,
			String condition) throws Exception {
		HashMap<String, Object> conditionMap = new HashMap<String, Object>();
		conditionMap.put("condition", condition);
		JSONObject teskObject =workflowFeignService.getTaskList(procressId);
		if (ObjectUtils.isNotEmpty(teskObject)) {
			JSONArray taskDetailArray = teskObject.getJSONArray("data");
			for (Object obj : taskDetailArray) {
				JSONObject detail = JSONObject.parseObject(JSONObject.toJSONString(obj));
				workflowFeignService.pickupAndCompleteTask(detail.getString("id"), conditionMap);
			}
		}
		return true;
	}
	public boolean checkExcuteTaskAuth(Long sequenceNbr, ReginParams userInfo) {
		Map<String,Object> map=	this.checkExcuteTaskAuthMap(sequenceNbr,userInfo);
		return Boolean.parseBoolean(map.get("checkFlag").toString());
	}
	public Map<String,Object> checkExcuteTaskAuthMap(Long sequenceNbr, ReginParams userInfo) {
		Map<String,Object> map = new HashMap<String,Object>();
		FailureDetailsDto failureDetailsDto = this.queryBySeq(sequenceNbr);
		// 获取送达部门的ID
		Integer failureEquipmentId = failureDetailsDto.getFailureEquipmentId();
		//获取上一级操作部门的Id
		FailureDetails details = this.baseMapper.selectById(sequenceNbr);
		String procressId = details.getProcessId();
		Long seq = userInfo.getDepartment().getSequenceNbr();
		JSONObject teskObject =workflowFeignService.getTaskList(procressId);
		if (ObjectUtils.isNotEmpty(teskObject)) {
			JSONArray taskDetailArray = teskObject.getJSONArray("data");
			for (Object obj : taskDetailArray) {
				JSONObject detail = JSONObject.parseObject(JSONObject.toJSONString(obj));
				String name = detail.getString("name");
				if (name.contains(EMERGENCY_COMMAND) ) {
					FailureAudit failureAuditDetail = failureAuditService.findByFaultId(sequenceNbr);
				      Long	auditDepartmentId = failureAuditDetail.getAuditDepartmentId();
						if(auditDepartmentId.intValue() == seq.intValue()) {
							map.put("taskId", detail.getString("id"));
							map.put("checkFlag", true);
							return map;
						}
				} else {
					if (failureEquipmentId.intValue() == seq.intValue()) {
						map.put("taskId", detail.getString("id"));
						map.put("checkFlag", true);
						return map;
					}
				}
			}
		}
		map.put("checkFlag", false);
		return map;
	}

	public Object getCurrentProcessHistoryTask(Long id) {
		FailureDetailsDto failureDetailsDto = this.queryBySeq(id);
		String processId = failureDetailsDto.getProcessId();
		return logger;

	}

	public static String buildOrderNo() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		String newDate = sdf.format(new Date());
		String result = "";
		Random random = new Random();
		for (int i = 0; i < 3; i++) {
			result += random.nextInt(10);
		}
		return newDate + result;
	}
}