package com.yeejoin.precontrol.common.service.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import com.yeejoin.precontrol.common.entity.HazardousWork;
import com.yeejoin.precontrol.common.entity.RiskWork;
import com.yeejoin.precontrol.common.entity.RiskWorkHazadousWork;
import com.yeejoin.precontrol.common.entity.RiskWorkMeasure;
import com.yeejoin.precontrol.common.entity.RiskWorkPersonRequirement;
import com.yeejoin.precontrol.common.entity.TaskRiskControl;
import com.yeejoin.precontrol.common.entity.publics.BaseEntity;
import com.yeejoin.precontrol.common.exception.CommonException;
import com.yeejoin.precontrol.common.mapper.PersonMapper;
import com.yeejoin.precontrol.common.mapper.RiskWorkMapper;
import com.yeejoin.precontrol.common.param.RiskWorkParam;
import com.yeejoin.precontrol.common.service.IHazardousWorkService;
import com.yeejoin.precontrol.common.service.IRiskWorkHazadousWorkService;
import com.yeejoin.precontrol.common.service.IRiskWorkMeasureService;
import com.yeejoin.precontrol.common.service.IRiskWorkPersonRequirementService;
import com.yeejoin.precontrol.common.service.IRiskWorkService;
import com.yeejoin.precontrol.common.service.ITaskRiskControlService;
import com.yeejoin.precontrol.common.utils.StringUtil;
import com.yeejoin.precontrol.common.vo.RiskWorkPersonVo;
import com.yeejoin.precontrol.common.vo.RiskWorkRequestVo;
import com.yeejoin.precontrol.common.vo.RiskWorkVo;

/**
 * 风险作业管理表 服务实现类
 *
 * @author duanwei
 * @date 2021-01-28
 */
@Service
public class RiskWorkServiceImpl extends ServiceImpl<RiskWorkMapper, RiskWork> implements IRiskWorkService {

	@Autowired
	IRiskWorkHazadousWorkService iRiskWorkHazadousWorkService;

	@Autowired
	IRiskWorkMeasureService iRiskWorkMeasureService;

	@Autowired
	IRiskWorkPersonRequirementService ipersonRequirementService;

	@Autowired
	PersonMapper personMapper;

	@Autowired
	IHazardousWorkService iHazardousWorkService;

	@Autowired
	ITaskRiskControlService iTaskRiskControlService;

	/**
	 * 3级安全考试,数据来源平台字典行业类型，约定写死
	 */
	private final String THREE_LEVEL_EXAM = "THREE_LEVEL_EXAM";

	@Override
	@Transactional(rollbackFor = Exception.class)
	public RiskWorkParam saveWithChild(RiskWorkParam riskWorkParam, String userId) {
		
		RiskWork riskWork = riskWorkParam.getRiskWork();
		riskWork.setCreateId(userId);
		List<RiskWorkMeasure> riskWorkMeasures = riskWorkParam.getRiskWorkMeasures() == null ? new ArrayList<>()
				: riskWorkParam.getRiskWorkMeasures();
		List<RiskWorkHazadousWork> riskWorkHazadousWorks = riskWorkParam.getRiskWorkHazadousWorks() == null
				? new ArrayList<>()
				: riskWorkParam.getRiskWorkHazadousWorks();
		List<RiskWorkPersonRequirement> riskWorkPersonRequirements = riskWorkParam
				.getRiskWorkPersonRequirements() == null ? new ArrayList<>()
						: riskWorkParam.getRiskWorkPersonRequirements();
		// 1.保存主表
		this.saveOrUpdate(riskWork);
		// 2.刪除子表
		this.deleteRiskWorkMeasure(riskWork.getId());
		this.deleteRiskWorkHazadousWork(riskWork.getId());
		this.deleteRiskWorkPersonRequirement(riskWork.getId());
		riskWorkMeasures.forEach(m -> m.setRiskWorkId(riskWork.getId()));
		riskWorkHazadousWorks.forEach(w -> w.setRiskWorkId(riskWork.getId()));
		riskWorkPersonRequirements.forEach(r -> r.setRiskWorkId(riskWork.getId()));
		// 3.保存子表
		if (!CollectionUtils.isEmpty(riskWorkMeasures)) {
			iRiskWorkMeasureService.saveOrUpdateBatch(riskWorkMeasures);
		}
		if (!CollectionUtils.isEmpty(riskWorkHazadousWorks)) {
			iRiskWorkHazadousWorkService.saveOrUpdateBatch(riskWorkHazadousWorks);
		}
		if (!CollectionUtils.isEmpty(riskWorkPersonRequirements)) {
			ipersonRequirementService.saveOrUpdateBatch(riskWorkPersonRequirements);
		}
		return riskWorkParam;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeWithChild(List<Long> ids) {
		ids.forEach(id -> {
			RiskWork riskWork = this.getById(id);
			if (riskWork == null) {
				return;
			}
			int useNum = this.countUseNum(id);
			if (useNum > 0) {
				throw new CommonException(700001, riskWork.getName() + ":在风险管控任务中使用，不能删除");
			}
			this.removeById(id);
			this.deleteRiskWorkMeasure(id);
			this.deleteRiskWorkHazadousWork(id);
			this.deleteRiskWorkPersonRequirement(id);
		});
		return true;
	}

	private int countUseNum(Long id) {
		LambdaQueryWrapper<TaskRiskControl> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(TaskRiskControl::getRiskWorkId, id);
		List<TaskRiskControl> taskRiskControls = iTaskRiskControlService.list(lambdaQueryWrapper);
		if (CollectionUtils.isEmpty(taskRiskControls)) {
			return 0;
		}
		return taskRiskControls.size();
	}

	@Override
	public RiskWorkParam getWithChildById(Long id) {
		RiskWorkParam riskWorkParam = new RiskWorkParam();
		RiskWork riskWork = this.getById(id);
		List<RiskWorkMeasure> riskWorkMeasures = this.getRiskWorkMeasures(id);
		List<RiskWorkHazadousWork> riskWorkHazadousWorks = this.getRiskWorkHazadousWorks(id);
		List<RiskWorkPersonRequirement> riskWorkPersonRequirements = this.getRiskWorkPersonRequirements(id);
		riskWorkParam.setRiskWork(riskWork);
		riskWorkParam.setRiskWorkMeasures(riskWorkMeasures);
		riskWorkParam.setRiskWorkHazadousWorks(riskWorkHazadousWorks);
		riskWorkParam.setRiskWorkPersonRequirements(riskWorkPersonRequirements);
		return riskWorkParam;
	}

	@Override
	public List<RiskWorkPersonVo> listPersonOfMatchCondition(Long riskWorkId, String personType, Long companyId,
			Long projectId, String name) {
		QueryWrapper<RiskWorkPersonRequirement> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(RiskWorkPersonRequirement::getRiskWorkId, riskWorkId)
				.eq(RiskWorkPersonRequirement::getPersonType, personType);
		List<RiskWorkPersonRequirement> list = ipersonRequirementService.list(wrapper);
		List<RiskWorkPersonVo> allPerson = new ArrayList<>();
		List<RiskWorkPersonVo> riskWorkPersonVoList = personMapper.queryPersonInComAndDept(companyId, projectId, name);
		List<Long> threeIds = this.getPassPersonThreeExam(companyId, projectId);

		if (!CollectionUtils.isEmpty(list)) {
			riskWorkPersonVoList.forEach(p -> {
				List<RiskWorkRequestVo> requestList = new ArrayList<>();
				for (RiskWorkPersonRequirement r : list) {
					boolean flag=false;
					RiskWorkRequestVo riskWorkRequestVo = new RiskWorkRequestVo();
					if (StringUtil.isNotEmpty(r.getWorkType()) && !"无".equals(r.getWorkType())) {
						riskWorkRequestVo.setWorkType(r.getWorkTypeName());
						if (!r.getWorkType().equals(p.getPostNameKey())) {
							riskWorkRequestVo.setWorkTypeMatch(false);
							flag=true;
						}
					}
					if (StringUtil.isNotEmpty(r.getQualification()) && !"无".equals(r.getQualification())) {
						riskWorkRequestVo.setQualification(r.getQualification());
						if (!r.getQualification().equals(p.getCertificateNameKey())) {
							riskWorkRequestVo.setQualificationMatch(false);flag=true;
						}
					}
					if (StringUtil.isNotEmpty(r.getSecExam()) && "1".equals(r.getSecExam())) {
						riskWorkRequestVo.setSecExam("三级安全考试");
						if (!threeIds.contains(p.getId())) {
							riskWorkRequestVo.setSecExamMatch(false);flag=true;
						}
					}
					if (StringUtil.isNotEmpty(r.getProSkillExam()) && !"无".equals(r.getProSkillExam())) {
						riskWorkRequestVo.setProSkillExam(r.getProSkillExamName());
						List<Long> proIds = this.getProSkillExamPerson(companyId, projectId, r.getProSkillExam());
						if (!proIds.contains(p.getId())) {
							riskWorkRequestVo.setProSkillExamMatch(false);flag=true;
						}
					}
					if (StringUtil.isNotEmpty(r.getKnowledge()) && !"无".equals(r.getKnowledge())) {
						riskWorkRequestVo.setKnowledge(r.getKnowledgeName());
						List<Long> ids = this.getKnowledgePerson(companyId, projectId, r.getKnowledge());
						if (!ids.contains(p.getId())) {
							riskWorkRequestVo.setKnowledgeMatch(false);flag=true;
						}
					}
					if(flag) 
					{
						requestList.add(riskWorkRequestVo);
					}
				}
				p.setRequestList(requestList);
			});
//			// TODO: 分支1：人员有要求
//			list.forEach(r -> {
//				List<RiskWorkPersonVo> riskWorkPersonVoList = personMapper.queryPersonInComAndDept(companyId, projectId,
//						name);
//				// 工种过滤
//				if (StringUtil.isNotEmpty(r.getWorkType()) && !"无".equals(r.getWorkType())) {
//					riskWorkPersonVoList.forEach(i -> {
//						if (!r.getWorkType().equals(i.getPostNameKey())) {
//							i.setWorkType(false);
//						}
//					});
//				}
//				// 资质过滤
//				if (StringUtil.isNotEmpty(r.getQualification()) && !"无".equals(r.getQualification())) {
//					riskWorkPersonVoList.forEach(i -> {
//						if (!r.getQualification().equals(i.getCertificateNameKey())) {
//							i.setQualification(false);
//						}
//					});
//				}
//				// 三级安全考试过滤 1-合格 2-无要求
//				if (StringUtil.isNotEmpty(r.getSecExam()) && "1".equals(r.getSecExam())) {
//					List<Long> ids = this.getPassPersonThreeExam(companyId, projectId);
//					riskWorkPersonVoList.forEach(i -> {
//						if (!ids.contains(i.getId())) {
//							i.setSecExam(false);
//						}
//					});
//				}
//				// 专业技能考试过滤
//				if (StringUtil.isNotEmpty(r.getProSkillExam()) && !"无".equals(r.getProSkillExam())) {
//					List<Long> ids = this.getProSkillExamPerson(companyId, projectId, r.getProSkillExam());
//					riskWorkPersonVoList.forEach(i -> {
//						if (!ids.contains(i.getId())) {
//							i.setProSkillExam(false);
//						}
//					});
//				}
//				// 知识 过滤
//				if (StringUtil.isNotEmpty(r.getKnowledge()) && !"无".equals(r.getKnowledge())) {
//					List<Long> ids = this.getKnowledgePerson(companyId, projectId, r.getKnowledge());
//					riskWorkPersonVoList.forEach(i -> {
//						if (!ids.contains(i.getId())) {
//							i.setKnowledge(false);
//						}
//					});
//				}
//				allPerson.addAll(riskWorkPersonVoList);
//			});
			allPerson.addAll(riskWorkPersonVoList);
		} else {
			// TODO: 分支2：人员没要求, 则为公司、项目下人
			List<RiskWorkPersonVo> riskWorkPersonVoList2 = personMapper.queryPersonInComAndDept(companyId, projectId,
					name);
			allPerson.addAll(riskWorkPersonVoList2);
		}
		// 因为风险作业人员要求可能会有多条数据会导致人员数据重复，所以对人员列表数据进行去重
		List<RiskWorkPersonVo> tempAllPerson = allPerson.stream()
				.collect(Collectors.collectingAndThen(
						Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(RiskWorkPersonVo::getUserId))),
						ArrayList::new));
		return tempAllPerson;
	}

	private String getWorkType(FeignClientResult<List<DictionarieValueModel>> resultDict, String postNameKey) {
		if (StringUtil.isNotEmpty(resultDict)) {
			DictionarieValueModel dictModel = resultDict.getResult().stream()
					.filter(dict -> dict.getDictDataKey().equals(postNameKey)).findFirst().get();
			if (StringUtil.isNotEmpty(dictModel)) {
				return dictModel.getDictDataValue();
			}
		}
		return null;
	}

	@Override
	public List<RiskWork> listAllWithDangerWork(String name,String orgCode) {
		// 1.按照风险作业名称模糊查询
		QueryWrapper<RiskWork> wrapper = new QueryWrapper<>();
		if (StringUtil.isNotEmpty(name)) {
			wrapper.lambda().like(RiskWork::getName, name);
		}
		if(StringUtil.isNotEmpty(orgCode)) {
			wrapper.lambda().like(RiskWork::getOrgCode, orgCode);
		}
		List<RiskWork> riskWorks = this.list(wrapper);
		// 2.循环查询拼接危险作业对象
		riskWorks.forEach(r -> {
			// 2.1查询风险作业子表，查询出管理的危险作业id
			List<RiskWorkHazadousWork> list = this.getRiskWorkHazadousWorks(r.getId());
			List<Long> ids = list.stream().map(RiskWorkHazadousWork::getHarzadousWorkId).collect(Collectors.toList());
			r.setHazardousWorks(new ArrayList<>());
			if (!CollectionUtils.isEmpty(ids)) {
				// 2.2查询出危险作业对象list
				QueryWrapper<HazardousWork> hazardousWorkQueryWrapper = new QueryWrapper<>();
				hazardousWorkQueryWrapper.lambda().in(BaseEntity::getId, ids);
				List<HazardousWork> hazardousWorks = iHazardousWorkService.list(hazardousWorkQueryWrapper);
				r.setHazardousWorks(hazardousWorks);
			}
		});
		return riskWorks;
	}

	@Override
	public RiskWorkVo getDetailByPlanId(Long taskRiskControlId) {
		return this.baseMapper.getDetailByPlanId(taskRiskControlId);
	}

	private List<Long> getKnowledgePerson(Long companyId, Long projectId, String knowledge) {
		Map<String, Object> param = new HashMap<>();
		param.put("companyId", companyId);
		param.put("projectId", projectId);
		param.put("industryType", knowledge);
		return personMapper.selectKnowledgePerson(param);
	}

	private List<Long> getProSkillExamPerson(Long companyId, Long projectId, String proSkillExam) {
		Map<String, Object> param = new HashMap<>();
		param.put("companyId", companyId);
		param.put("projectId", projectId);
		param.put("examTemplateId", proSkillExam);
		return personMapper.selectProSkillExamPerson(param);
	}

	private List<Long> getPassPersonThreeExam(Long companyId, Long projectId) {
		return personMapper.selectPassPersonThreeExam(companyId, projectId, THREE_LEVEL_EXAM);
	}

	private Map<String, String> getDictsMap(String dictCode) {
		Map<String, String> map = new LinkedHashMap<>();
		FeignClientResult<List<DictionarieValueModel>> result1 = Systemctl.dictionarieClient.dictValues(dictCode);
		if (result1 != null) {
			map = result1.getResult().stream().collect(
					Collectors.toMap(DictionarieValueModel::getDictDataKey, DictionarieValueModel::getDictDataValue));
		}
		return map;
	}

	private List<RiskWorkPersonRequirement> getRiskWorkPersonRequirements(Long id) {
		QueryWrapper<RiskWorkPersonRequirement> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(RiskWorkPersonRequirement::getRiskWorkId, id);
		return ipersonRequirementService.list(wrapper);
	}

	private List<RiskWorkHazadousWork> getRiskWorkHazadousWorks(Long id) {
		QueryWrapper<RiskWorkHazadousWork> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(RiskWorkHazadousWork::getRiskWorkId, id);
		List<RiskWorkHazadousWork> list = iRiskWorkHazadousWorkService.list(wrapper);
		list.forEach(i -> {
			HazardousWork hazardousWork = iHazardousWorkService.getById(i.getHarzadousWorkId());
			i.setHarzadousWorkName(hazardousWork != null ? hazardousWork.getName() : null);
		});
		return list;
	}

	private List<RiskWorkMeasure> getRiskWorkMeasures(Long id) {
		QueryWrapper<RiskWorkMeasure> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(RiskWorkMeasure::getRiskWorkId, id);
		return iRiskWorkMeasureService.list(wrapper);
	}

	private void deleteRiskWorkMeasure(Long id) {
		QueryWrapper<RiskWorkMeasure> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(RiskWorkMeasure::getRiskWorkId, id);
		iRiskWorkMeasureService.getBaseMapper().delete(wrapper);
	}

	private void deleteRiskWorkHazadousWork(Long id) {
		QueryWrapper<RiskWorkHazadousWork> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(RiskWorkHazadousWork::getRiskWorkId, id);
		iRiskWorkHazadousWorkService.getBaseMapper().delete(wrapper);
	}

	private void deleteRiskWorkPersonRequirement(Long id) {
		QueryWrapper<RiskWorkPersonRequirement> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(RiskWorkPersonRequirement::getRiskWorkId, id);
		ipersonRequirementService.getBaseMapper().delete(wrapper);
	}
}
