/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.security.trans.dailyDuties.service.impl;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.security.common.Constant;
import org.security.common.eum.OtherDataEnum;
import org.security.common.util.DataFormatUtil;
import org.security.common.util.ExcelUtil;
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.ht.vo.common.UploadVO;
import org.security.system.feign.ISysClient;
import org.security.trans.common.service.IFileService;
import org.security.trans.dailyDuties.dto.InspectionLineDTO;
import org.security.trans.dailyDuties.entity.Inspection;
import org.security.trans.dailyDuties.entity.InspectionLine;
import org.security.trans.dailyDuties.dto.InspectionLineExcelDTO;
import org.security.trans.dailyDuties.vo.InspectionLineVO;
import org.security.trans.dailyDuties.mapper.InspectionLineMapper;
import org.security.trans.dailyDuties.service.IInspectionLineService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.security.trans.dailyDuties.vo.InspectionVO;
import org.springblade.core.log.exception.ServiceException;
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.Func;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.security.common.Constant.*;

/**
 * 任务-监督检查明细 服务实现类
 *
 * @author BladeX
 * @since 2022-03-25
 */
@Slf4j
@Service
@AllArgsConstructor
public class InspectionLineServiceImpl extends ServiceImpl<InspectionLineMapper, InspectionLine> implements IInspectionLineService {
	private final IFlowClient flowClient;
	private final ISysClient sysClient;
	private final IFileService fileService;

	@Override
	public boolean saveInspectionLine(InspectionLineDTO inspectionLineDTO) {
		super.saveOrUpdate(inspectionLineDTO);
		List<UploadVO> fileList = inspectionLineDTO.getCheckPicList();
		List<UploadVO> fileList2 = inspectionLineDTO.getRectifyPicList();
		if (Objects.nonNull(fileList) && !fileList.isEmpty()) {
			fileService.saveAttachments(fileList, inspectionLineDTO.getId());
		}
		if (Objects.nonNull(fileList2) && !fileList2.isEmpty()) {
			fileService.saveAttachments(fileList2, inspectionLineDTO.getId());
		}
		return true;
	}


	@Override
	public List<String> getChildrenDeptId(String aimDeptId) {
		return baseMapper.getChildrenDeptId(aimDeptId);
	}

	@Override
	public IPage<InspectionLineVO> selectInspectionLinePage(IPage<InspectionLineVO> page, InspectionLineDTO inspectionLineDTO) {
		List<String> formIdList = Func.toStrList(inspectionLineDTO.getFormIds());
		log.info("=======formIdList========{}", formIdList);
		List<InspectionLineVO> res = baseMapper.selectInspectionLinePage(page, inspectionLineDTO, formIdList);
		return page.setRecords(res);
	}

	/**
	 * 提交明细的整改结果，更新整改状态
	 *
	 * @param inspectionLineDTO 检查明细数据
	 * @return
	 * @throws ParseException
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean handinRectify(InspectionLineDTO inspectionLineDTO) throws ParseException {
		InspectionLine inspectionLine = Func.copy(inspectionLineDTO, InspectionLine.class);
//		if ("1".equals(inspectionLine.getNeedContinue())) {//	需要持续整改
//			InspectionLine nLine = Func.copy(inspectionLine, InspectionLine.class);
//			nLine.setId(null);
//			nLine.setRectifyDescribe("");
//			nLine.setFlag("2");
//			nLine.setNeedContinue("0");
//			nLine.setStatus(PROBLEM_STATE_WAIT_RECTIFY);
//			nLine.setState(HANDIN_STATE_DRAFT);
//			nLine.setRectifyDeadline(inspectionLineDTO.getNewDeadline());
//			this.saveOrUpdate(nLine);//新增一条对应的待整改明细
//			//存储整改后附件
//			fileService.saveAttachments(inspectionLineDTO.getRectifyPicList(),inspectionLine.getId());
//		}
		this.updateById(inspectionLine);
		//存储整改后附件
		fileService.saveAttachments(inspectionLineDTO.getRectifyPicList(),inspectionLine.getId());
		//		挂载流程
		R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(ProcessConstant.INSPECTION_LINE_KEY);
		if (definitionRes.isSuccess()) {
			inspectionLine.setProcessDefinitionId(definitionRes.getData().getId());
		} else {
			throw new ServiceException("未查询到流程定义，开启流程失败");
		}
		R<Integer> deptCategory = sysClient.getDeptCategory(Long.valueOf(AuthUtil.getUser().getDeptId()));
		if (!deptCategory.isSuccess()) {
			throw new ServiceException("查询部门类型失败，请检查后再试！");
		}
		String businessTable = FlowUtil.getBusinessTable(InspectionLine.class);
//			查询主表inspection的信息，用于获取检查方、检查类型信息------
		List<InspectionVO> res = baseMapper.selectRelInspection(inspectionLineDTO.getFormId());
		String flowCheckType = "inside";
		R<Integer> sendDeptCategory = R.data(1);
		if (Func.isNotEmpty(res)) {
			Inspection inspection = Func.copy(res.get(0), Inspection.class);
			if ("3".equals(inspection.getCheckType())) {
				flowCheckType = "outside";
			} else {
				sendDeptCategory = sysClient.getDeptCategory(Long.valueOf(inspection.getInspectDep()));
				if (!sendDeptCategory.isSuccess()) {
					throw new ServiceException("查询检查方部门类型失败，请检查后再试！");
				}
			}
		}

		// 行内检查或外部检查（行内检查：inside，外部检查：outside）、检查方类型（总行：1，分行：2）
		Kv variables = Kv.create()
			.set("deptCategory", deptCategory.getData())
			.set(ProcessConstant.BUSINESS_ID_KEY, inspectionLine.getId())
			.set(ProcessConstant.START_PROC_USER_ID, AuthUtil.getUserId())
			.set("checkType", flowCheckType)
			.set("sendDeptCategory", sendDeptCategory.getData());
		R<BladeFlow> result = flowClient.startProcessInstanceById(inspectionLine.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(inspectionLine.getId())), variables);
		if (result.isSuccess()) {
			inspectionLine.setRectifyDate(DataFormatUtil.getNowDate());
			inspectionLine.setState(HANDIN_STATE_AUDIT);
			//	业务状态：根据整改期限及当前日期判断是否超时整改
			inspectionLine.setStatus(inspectionLine.getRectifyDeadline().before(DataFormatUtil.getLocalDate()) ? PROBLEM_STATE_OVERTIME_SUBMIT : PROBLEM_STATE_SUBMIT);
			inspectionLine.setProcessInstanceId(result.getData().getProcessInstanceId());

		} else {
			throw new ServiceException("开启流程失败");
		}
		this.updateById(inspectionLine);
		if ("1".equals(inspectionLine.getFlag())) {
			updateInspection(inspectionLine);
		}
		return true;
	}

	/**
	 *检查相关的主表状态，更新主表状态
	 * @param inspectionLine
	 */
	private void updateInspection(InspectionLine inspectionLine) {
		Inspection inspection = baseMapper.selectRelInspection(inspectionLine.getFormId()).get(0);
		//	查出此条检查明细所属主表的所有一般整改明细（不考虑持续整改明细）
		List<InspectionLineVO> res2 = baseMapper.selectLinesByInspectionLine(inspectionLine);
		if (Func.isNotEmpty(res2)) {
			//待整改的
			List<InspectionLineVO> collect1 = res2.stream().filter(item -> PROBLEM_STATE_WAIT_RECTIFY.equals(item.getStatus())).collect(Collectors.toList());
			int waitRectify = collect1.size();
			//超期待整改的
			List<InspectionLineVO> collect2 = res2.stream().filter(item -> PROBLEM_STATE_OVERTIME.equals(item.getStatus())).collect(Collectors.toList());
			int overTimeRectify = collect2.size();
			//超期完成整改的
			List<InspectionLineVO> collect3 = res2.stream().filter(item -> PROBLEM_STATE_OVERTIME_SUBMIT.equals(item.getStatus())).collect(Collectors.toList());
			int overtimeDoneRectify = collect3.size();

			if (overTimeRectify > 0) {
				inspection.setStatus(PROBLEM_STATE_OVERTIME);
			} else if (waitRectify > 0) {
				inspection.setStatus(PROBLEM_STATE_WAIT_RECTIFY);
			} else if (overtimeDoneRectify > 0) {
				inspection.setStatus(PROBLEM_STATE_OVERTIME_SUBMIT);
				inspection.setRectifyStatus("1");
			} else {
				inspection.setStatus(PROBLEM_STATE_SUBMIT);
				inspection.setRectifyStatus("1");
			}
			baseMapper.updateInspection(inspection);
		}
	}

	/**
	 * 删除信息
	 *
	 * @param toLongList 主表关联id
	 * @return
	 */
	@Override
	public boolean removeData(List<Long> toLongList) {
		return baseMapper.removeData(toLongList);
	}

	/**
	 * 导入检查结果明细
	 *
	 * @param id   主表记录id
	 * @param file 文件内容
	 * @return
	 */
	@Override
	public boolean saveData(String id, MultipartFile file) {
		ArrayList<InspectionLine> lines = new ArrayList<>();
		//读取excel文件内容
		List<InspectionLineExcelDTO> list = ExcelUtil.read(file, InspectionLineExcelDTO.class);
		if (Func.isNotEmpty(list)) {
			list.forEach(item -> {
				InspectionLine inspectionLine = Func.copy(item, InspectionLine.class);
				inspectionLine.setDescription(Func.isBlank(item.getDescription()) ? "" : item.getDescription());
				inspectionLine.setFormId(id);
				inspectionLine.setHasProblem(OtherDataEnum.parseByLabel(inspectionLine.getHasProblem()).getCode());
				inspectionLine.setState(HANDIN_STATE_DRAFT);
				inspectionLine.setStatus("1".equals(inspectionLine.getHasProblem()) ? PROBLEM_STATE_WAIT_RECTIFY : PROBLEM_STATE_NO_PROBLEM);
				lines.add(inspectionLine);
			});
		}
		return this.saveBatch(lines);
	}

	@Override
	public InspectionLineVO getDetail(String id) {
		InspectionLine detail = super.getById(id);
		InspectionLineVO inspectionLineVO = Func.copy(detail, InspectionLineVO.class);
		//整改前图片
		inspectionLineVO.setCheckPicList(fileService.getAttachments(detail.getId(), detail.getCheckPic()));
		//整改后图片
		inspectionLineVO.setRectifyPicList(fileService.getAttachments(detail.getId(), detail.getRectifyPic()));
		return inspectionLineVO;
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public R afterFlowFinished(String id, Boolean pass, Map<String, Object> var) {
		Boolean result = false;
		String state;
		if (null == pass) {
			state = ProcessConstant.CANCEL_STATE;
		} else if (pass) {
			state = ProcessConstant.PASS_STATE;
		} else {
			state = ProcessConstant.REJECT_STATE;
		}
		result = this.updateStateById(id, state);
		if (result){
			InspectionLine inspectionLine = this.getById(id);
			//审批通过持续整改记录创建
			if ("1".equals(inspectionLine.getNeedContinue()) && Func.isNotEmpty(pass)){
				InspectionLine line = Func.copy(inspectionLine, InspectionLine.class);
				line.setFlag(Constant.PROBLEM_STATE_CONTINUED);
				line.setState(Constant.HANDIN_STATE_DRAFT);
				line.setStatus(Constant.PROBLEM_STATE_WAIT_RECTIFY);
				line.setId(null);
				line.setNeedContinue("0");
				line.setRectifyDeadline(inspectionLine.getNewDeadline());
				line.setRectifyDescribe("");
				this.save(line);
				//获取附件
				List<UploadVO> checkPics = fileService.getAttachments(inspectionLine.getId(), inspectionLine.getCheckPic());
				List<UploadVO> rectifyPics = fileService.getAttachments(inspectionLine.getId(), inspectionLine.getRectifyPic());
				//保存相关附件
				fileService.saveAttachments(checkPics,line.getId());
				fileService.saveAttachments(rectifyPics,line.getId());
			}

		}
		return R.status(result);
	}
}
