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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.entity.Dept;
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.MaterialDataDTO;
import org.security.trans.dataStatistics.dto.StatisticsDataDTO;
import org.security.trans.dataStatistics.vo.MaterialDataVO;
import org.security.trans.prevent.dto.PreventMaterialDTO;
import org.security.trans.prevent.entity.PreventMaterial;
import org.security.trans.prevent.mapper.PreventMaterialMapper;
import org.security.trans.prevent.service.IPreventMaterialService;
import org.security.trans.prevent.vo.PreventMaterialVO;
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.Date;
import java.util.List;
import java.util.Objects;

import static org.security.common.Constant.TASK_HANDIN_STATE_OVERTIME_SUBMIT;
import static org.security.common.Constant.TASK_HANDIN_STATE_SUBMIT;

/**
 * 案件材料报送表 服务实现类
 *
 * @author BladeX
 * @since 2022-07-07
 */
@AllArgsConstructor
@Service
public class PreventMaterialServiceImpl extends ServiceImpl<PreventMaterialMapper, PreventMaterial> implements IPreventMaterialService {

	private final IFileService fileService;
	private final PreventMaterialMapper preventMaterialMapper;
	private final IFlowClient flowClient;
	private final ISysClient sysClient;
	private final IDepartmentService departmentService;

	@Override
	public IPage<PreventMaterialVO> getPage(PreventMaterialVO preventMaterialVO, Query query) {
		String user = String.valueOf(AuthUtil.getUserId());
		IPage<PreventMaterialVO> page = Condition.getPage(query);
		List<PreventMaterialVO> preventMaterialVos = preventMaterialMapper.getPage(page, preventMaterialVO);
		preventMaterialVos.forEach(item->{
		});
		return page.setRecords(preventMaterialVos);
	}

	@Override
	public PreventMaterialVO getDetail(PreventMaterial preventMaterial) {
		QueryWrapper<PreventMaterial> queryWrapper = Condition.getQueryWrapper(preventMaterial);
		PreventMaterial material = this.getOne(queryWrapper);
		List<UploadVO> attachments = fileService.getAttachments(material.getId(),material.getGroupName());
		PreventMaterialVO preventMaterialVO = BeanUtil.copyProperties(material, PreventMaterialVO.class);
		preventMaterialVO.setFileList(attachments);
		return preventMaterialVO;
	}

	@Override
	public R saveMaterial(PreventMaterialDTO preventMaterialDTO) {
		PreventMaterial preventMaterial = BeanUtil.copyProperties(preventMaterialDTO, PreventMaterial.class);
		if(Func.isNull(preventMaterial.getDeptId()) || Func.isBlank(preventMaterial.getDeptId())){
			preventMaterial.setDeptId(AuthUtil.getDeptId());
		}
		preventMaterial.setDeptName(departmentService.getById(preventMaterial.getDeptId()).getDeptName());
		this.saveOrUpdate(preventMaterial);
		List<UploadVO> fileList = preventMaterialDTO.getFileList();
		if (Objects.nonNull(fileList) && !fileList.isEmpty()) {
			fileService.saveAttachments(fileList, preventMaterial.getId());
		}
		return R.data(preventMaterial);
	}

	@Override
	public boolean handin(PreventMaterialDTO preventMaterialDTO) {
		if(Func.isNull(preventMaterialDTO.getDeptId()) || Func.isBlank(preventMaterialDTO.getDeptId())){
			preventMaterialDTO.setDeptId(AuthUtil.getDeptId());
		}
		preventMaterialDTO.setDeptName(departmentService.getById(preventMaterialDTO.getDeptId()).getDeptName());
		R material = saveMaterial(preventMaterialDTO);
		PreventMaterial preventMaterial = (PreventMaterial) material.getData();
		R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(ProcessConstant.PREVENT_MATERIAL_KEY);
		if (definitionRes.isSuccess()) {
			preventMaterial.setProcessDefinitionId(definitionRes.getData().getId());
		} else {
			throw new ServiceException("开启流程失败");
		}
		String businessTable = FlowUtil.getBusinessTable(PreventMaterial.class);
		R<Dept> deptRes = sysClient.getDept(Long.valueOf(preventMaterial.getDeptId()));
		if (!deptRes.isSuccess()) {
			throw new ServiceException("开启流程失败，未能查询到部门信息");
		}
		Kv variables = Kv.create()
			.set("category", preventMaterialDTO.getCommitRoleType())
			.set(ProcessConstant.BUSINESS_ID_KEY, preventMaterial.getId())
			.set(ProcessConstant.START_PROC_USER_ID, AuthUtil.getUserId());
		R<BladeFlow> result = flowClient.startProcessInstanceById(preventMaterial.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(preventMaterial.getId())), variables);
		if (result.isSuccess()) {
			log.debug("流程已启动,流程ID:" + result.getData().getProcessInstanceId());
			// 返回流程id写入preventMaterial
			preventMaterial.setProcessInstanceId(result.getData().getProcessInstanceId());
			preventMaterial.setState(Constant.HANDIN_STATE_AUDIT);
			preventMaterial.setSubmitTime(DateUtil.now());
			Date deadline = preventMaterial.getDeadline();
			if(!Func.isNull(deadline) && Func.isNotEmpty(deadline)){
				preventMaterial.setStatus(deadline.after(new Date())?TASK_HANDIN_STATE_SUBMIT:TASK_HANDIN_STATE_OVERTIME_SUBMIT);//业务状态
			}else{
				preventMaterial.setStatus(TASK_HANDIN_STATE_SUBMIT);
			}
			this.saveOrUpdate(preventMaterial);
			return true;
		} else {
			throw new ServiceException("开启流程失败");
		}
	}

	@Override
	public List<PreventMaterial> getPreventList(String status) {
		QueryWrapper<PreventMaterial> wrapper = new QueryWrapper<>();
		wrapper.eq("STATUS", status);
		wrapper.eq("DEL_FLAG","0");
		return baseMapper.selectList(wrapper);
	}

	@Override
	public PreventMaterial getPreventMaterialDatas(String id, String deptId, Date begin, Date end) {
		return this.getOne(new QueryWrapper<PreventMaterial>().lambda()
			.eq(Func.isNotEmpty(id),PreventMaterial::getTaskId,id)
			.eq(Func.isNotEmpty(deptId),PreventMaterial::getDeptId,deptId)
			.ge(Func.isNotEmpty(begin),PreventMaterial::getCreatedTime,begin)
			.le(Func.isNotEmpty(end),PreventMaterial::getCreatedTime,end));
	}

	@Override
	public List<MaterialDataVO> getAimStatisticsData(MaterialDataDTO materialDataDTO, List<String> aimDepts) {
		return baseMapper.getAimStatisticsData(materialDataDTO,aimDepts);
	}

}
