package org.security.trans.prevent.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.security.common.Constant;
import org.security.flow.core.constant.ProcessConstant;
import org.security.flow.core.entity.BladeFlow;
import org.security.flow.core.entity.BladeFlowDef;
import org.security.flow.core.feign.IFlowClient;
import org.security.flow.core.utils.FlowUtil;
import org.security.system.feign.ISysClient;
import org.security.trans.basic.service.IDepartmentService;
import org.security.trans.common.service.IFileService;
import org.security.ht.vo.common.UploadVO;
import org.security.trans.dataStatistics.dto.StatisticsDataDTO;
import org.security.trans.dataStatistics.vo.RiskDataVO;
import org.security.trans.prevent.entity.PreventRisk;
import org.security.trans.prevent.mapper.PreventRiskMapper;
import org.security.trans.prevent.service.IPreventRiskService;
import org.security.trans.prevent.vo.PreventRiskVO;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * 风险提示表 服务实现类
 *
 * @author BladeX
 * @since 2022-07-07
 */
@AllArgsConstructor
@Service
public class PreventRiskServiceImpl extends ServiceImpl<PreventRiskMapper, PreventRisk> implements IPreventRiskService {

	private final IFileService fileService;
	private final PreventRiskMapper preventRiskMapper;
	private final IFlowClient flowClient;
	private final ISysClient sysClient;
	private final IDepartmentService departmentService;

	@Override
	public IPage<PreventRiskVO> getPage(PreventRiskVO preventRiskVO, Query query) {
		List<PreventRiskVO> vos = new ArrayList<>();
		String user = String.valueOf(AuthUtil.getUserId());
		IPage<PreventRiskVO> page = Condition.getPage(query);
		List<PreventRiskVO> preventRiskVOS = preventRiskMapper.getPage(page, preventRiskVO);
		preventRiskVOS.forEach(item -> {
			//当前登录用户创建的数据
			if (user.equals(item.getCreatedBy())){
				vos.add(item);
			}
		});
		//其他用户提报且状态为-审批完成的数据
		List<PreventRiskVO> collect = preventRiskVOS.stream().filter(item -> Constant.HANDIN_STATE_FINISH.equals(item.getState())).collect(Collectors.toList());
		vos.addAll(collect);
		ArrayList<PreventRiskVO> list = vos.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PreventRiskVO::getId))), ArrayList::new));
		return page.setRecords(list);
	}

	@Override
	public PreventRiskVO getDetail(PreventRisk preventRisk) {
		QueryWrapper<PreventRisk> queryWrapper = Condition.getQueryWrapper(preventRisk);
		PreventRisk risk = this.getOne(queryWrapper);
		PreventRiskVO preventRiskVO = BeanUtil.copyProperties(risk, PreventRiskVO.class);
		preventRiskVO.setFileList(fileService.getAttachments(risk.getId(), risk.getGroupName()));
		return preventRiskVO;
	}

	@Override
	public List<RiskDataVO> getAimStatisticsData(StatisticsDataDTO statisticsDataDTO, List<String> aimDepts) {
		return baseMapper.getAimStatisticsData(statisticsDataDTO,aimDepts);
	}

	@Override
	public boolean saveRisk(PreventRiskVO preventRiskVO) {
		PreventRisk preventRisk = BeanUtil.copyProperties(preventRiskVO, PreventRisk.class);
		if(Func.isNull(preventRisk.getDeptId()) || Func.isBlank(preventRisk.getDeptId())){
			preventRisk.setDeptId(AuthUtil.getDeptId());
		}
		preventRisk.setDeptName(departmentService.getById(AuthUtil.getDeptId()).getDeptName());
		this.saveOrUpdate(preventRisk);
		List<UploadVO> fileList = preventRiskVO.getFileList();
		if (Func.isNotEmpty(fileList)) {
			fileService.saveAttachments(fileList, preventRisk.getId());
		}
		return this.saveOrUpdate(preventRisk);
	}

	@Override
	public boolean handinRisk(PreventRiskVO preventRiskVO) {
		PreventRisk preventRisk = BeanUtil.copyProperties(preventRiskVO, PreventRisk.class);
		if(Func.isNull(preventRisk.getDeptId()) || Func.isBlank(preventRisk.getDeptId())){
			preventRisk.setDeptId(AuthUtil.getDeptId());
		}
		preventRisk.setDeptName(departmentService.getById(AuthUtil.getDeptId()).getDeptName());
		R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(ProcessConstant.PREVENT_RISK_KEY);
		if (definitionRes.isSuccess()) {
			preventRisk.setProcessDefinitionId(definitionRes.getData().getId());
		} else {
			throw new ServiceException("开启流程失败");
		}
		if(Func.isNull(preventRisk.getDeptId()) || Func.isBlank(preventRisk.getDeptId())){
			preventRisk.setDeptId(AuthUtil.getDeptId());
		}
		this.saveOrUpdate(preventRisk);

		String businessTable = FlowUtil.getBusinessTable(PreventRisk.class);

//			保存相关附件
		List<UploadVO> fileList = preventRiskVO.getFileList();
		if (Func.isNotEmpty(fileList)) {
			fileService.saveAttachments(fileList, preventRisk.getId());
		}
		R<Integer> deptCategory = sysClient.getDeptCategory(Long.valueOf(AuthUtil.getUser().getDeptId()));
		if (!deptCategory.isSuccess()) {
			throw new ServiceException("查询部门类型失败，请检查后再试！");
		}
		// 启动流程
		Kv variables = Kv.create()
			.set(ProcessConstant.BUSINESS_ID_KEY, preventRisk.getId())
			.set("deptCategory", deptCategory.getData())
			.set(ProcessConstant.START_PROC_USER_ID, AuthUtil.getUserId());
		R<BladeFlow> result = flowClient.startProcessInstanceById(preventRisk.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(preventRisk.getId())), variables);
		if (result.isSuccess()) {
			log.debug("流程已启动,流程ID:" + result.getData().getProcessInstanceId());
			// 返回流程id写入preventRisk
			preventRisk.setProcessInstanceId(result.getData().getProcessInstanceId());
			preventRisk.setSubmitTime(DateUtil.now());
			preventRisk.setState(Constant.HANDIN_STATE_AUDIT);
			updateById(preventRisk);
		} else {
			throw new ServiceException("开启流程失败");
		}
		return true;
	}
}
