package com.lz.modules.flow.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lz.common.emun.ChartOptType;
import com.lz.common.emun.CheckStaffType;
import com.lz.common.utils.R;
import com.lz.common.utils.StringUtil;
import com.lz.modules.app.entity.StaffEntity;
import com.lz.modules.app.entity.StaffSimpleInfo;
import com.lz.modules.app.service.StaffService;
import com.lz.modules.flow.dao.FlowStartMapper;
import com.lz.modules.flow.entity.*;
import com.lz.modules.flow.model.DepartManagers;
import com.lz.modules.flow.model.ResultModelDto;
import com.lz.modules.flow.model.ResultTagetLibDto;
import com.lz.modules.flow.service.*;
import com.lz.modules.performance.service.ResultTagetLibService;
import com.lz.modules.sys.entity.app.ResultDetail;
import com.lz.modules.sys.entity.app.ResultRecord;
import com.lz.modules.sys.service.app.ResultDetailService;
import com.lz.modules.sys.service.app.ResultRecordService;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* <p>
* 发起考核表 服务类
* </p>
*
* @author quyixiao
* @since 2020-10-13
*/

@Service
public class FlowStartServiceImpl extends ServiceImpl<FlowStartMapper, FlowStart> implements FlowStartService {


    @Autowired
	private FlowStartMapper flowStartMapper;

	@Autowired
	private EvaluationStartStaffService evaluationStartStaffService;

	@Autowired
	private ResultModelService resultModelService;

	@Autowired
	private FlowChartDetailRecordService flowChartDetailRecordService;

	@Autowired
	private FlowService flowService;

	@Autowired
	private FlowApprovalRoleService flowApprovalRoleService;

	@Autowired
	private FlowChartService flowChartService;

	@Autowired
	private ResultRecordService resultRecordService;

	@Autowired
	private ResultDetailService resultDetailService;

	@Autowired
	private ResultTagetLibService resultTagetLibService;

	@Autowired
	private StaffService staffService;

	@Autowired
	private EvaluationGroupService evaluationGroupService;




	@Override
	public FlowStart selectFlowStartById(Long id){
		return flowStartMapper.selectFlowStartById(id);
	}



	@Override
	public Long insertFlowStart(FlowStart flowStart){
		return flowStartMapper.insertFlowStart(flowStart);
	}



	@Override
	public int updateFlowStartById(FlowStart flowStart){
		return flowStartMapper.updateFlowStartById(flowStart);
	}



	@Override
	public int updateCoverFlowStartById(FlowStart flowStart){
		return flowStartMapper.updateCoverFlowStartById(flowStart);
	}



	@Override
	public int deleteFlowStartById(Long id){
		return flowStartMapper.deleteFlowStartById(id);
	}

	@Override
	public FlowStart selectFlowStartByName(String name){
		return flowStartMapper.selectFlowStartByName(name);
	}

	@Override
	public R saveStart(FlowStart flowStart){
		//下面生成或者合并发起绩效
		if(flowStart.getStartTime() == null){
			return R.error("未设置有效考核月份");
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月");
		String startDate = sdf.format(flowStart.getStartTime());

		if(flowStart.getCycleType().intValue() != 0){
			//月份
			if(flowStart.getEndTime() == null){
				return R.error("未设置有效考核结束月份");
			}
			String endDate = sdf.format(flowStart.getStartTime());
			flowStart.setName(startDate + "-" + endDate + "绩效考核");
		}else{
			flowStart.setName(startDate + "绩效考核");
		}
		FlowStart flowStart1 = selectFlowStartByName(flowStart.getName());
		if(flowStart1 == null){
			insertFlowStart(flowStart);
		}else{

			flowStart.setId(flowStart1.getId());
		}



		Map<String, List<StaffEntity>> staffManages = new HashedMap();//部门(id+几级)和部门几级管理对应关系，减少数据库查找
		//下面开始初始化流程
		List<Long> ids = Arrays.stream(flowStart.getGroupIds().split(",")).map(new Function<String, Long>() {
			@Override
			public Long apply(String s) {
				return Long.parseLong(s);
			}
		}).collect(Collectors.toList());
		List<EvaluationGroup> evaluationGroups = evaluationGroupService.selectEvaluationGroupByIds(ids);

		for (int n = 0; n < evaluationGroups.size(); n++
		) {
			EvaluationGroup evaluationGroup = evaluationGroups.get(n);
			//下面初始化员工考核流程
			List<StaffSimpleInfo> staffIds = evaluationGroupService.selectAllStaffSimpleInfoByGroupId(evaluationGroup);

			if(staffIds.size() == 0){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//事务回滚

				return R.error(evaluationGroup.getName() + "——无有效考核人员");
			}
			List<ResultModelDto> resultModelDtos = resultModelService.selectResultDtoByGroupId(evaluationGroup.getId());
			if(resultModelDtos.size() == 0){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//事务回滚
				return R.error(evaluationGroup.getName() + "——没有设置考核模板");
			}

			List<FlowChart> flowCharts = flowChartService.selectFlowChartsByGroupId(evaluationGroup.getId());
			if(flowCharts.size() == 0){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//事务回滚
				return R.error(evaluationGroup.getName() + "——没有绩效流程节点");
			}
			List<FlowChartDetailRecord> flowChartDetailRecords = new ArrayList<>();
			for (FlowChart chart:flowCharts
				 ) {//按照节点顺序获取正确的流程
				List<FlowChartDetailRecord> flowChartDetailRecords1
						= flowChartDetailRecordService.selectFlowChartDetailRecordByGroupIdAndChartId(evaluationGroup.getId(), chart.getId());
				flowChartDetailRecords.addAll(flowChartDetailRecords1);
			}

			if(flowChartDetailRecords.size() == 0){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//事务回滚
				return R.error(evaluationGroup.getName() + "——没有设置考核流程");
			}
			Map<Long, String> chartNameMaps =
					flowCharts.stream().collect(Collectors.toMap(FlowChart::getId, FlowChart::getName));//流程节点与流程名称对应map，下面多次循环，减少数据库查找

			List<StaffEntity> staffManagers = null;
			if(!StringUtil.isEmpty(evaluationGroup.getManagerIds())){
				List<Long> mIds = Arrays.stream(evaluationGroup.getManagerIds().split(","))
						.map(new Function<String, Long>() {
							@Override
							public Long apply(String s) {
								return Long.parseLong(s);
							}
						}).collect(Collectors.toList());
				//查找在职的管理人员
				staffManagers = staffService.selectOnJobByIds(mIds);

			}
			if(staffManagers == null || staffManagers.size() == 0){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//事务回滚
				return R.error(evaluationGroup.getName() + "——没有设置绩效管理人员");
			}

			//下面拷贝一份考评组信息发起后所使用的考评组id为复制后的id
			evaluationGroup.setCopyId(evaluationGroup.getId());
			evaluationGroup.setId(null);
			evaluationGroup.setGmtCreate(null);
			evaluationGroup.setGmtModified(null);
			evaluationGroupService.insertEvaluationGroup(evaluationGroup);

			//拷贝考评组的指标信息
			List<ResultTagetLib> resultTagetLibs = new ArrayList<>();

			for (ResultModelDto dto:resultModelDtos
			) {


				dto.setEvaluationGroupId(evaluationGroup.getId());//设置拷贝组的id
				//下面拷贝一份考评组信息的维度信息
				ResultModel resultModel = new ResultModel();
				BeanUtils.copyProperties(dto, resultModel);
				resultModel.setId(null);
				resultModelService.insertResultModel(resultModel);

				List<ResultTagetLibDto> libDtos = resultTagetLibService.selectResultTagetLibDtoByModelId(dto.getId());
				dto.setTagetLibs(libDtos);
				for (ResultTagetLibDto libDto: libDtos
				) {
					//下面拷贝考评组里面的指标信息
					ResultTagetLib resultTagetLib = new ResultTagetLib();
					BeanUtils.copyProperties(libDto, resultTagetLib);
					resultTagetLib.setModelId(resultModel.getId());//设置新的维度id
					resultTagetLib.setId(null);
					resultTagetLibs.add(resultTagetLib);
				}
			}
			if(resultTagetLibs.size() > 0){
				//插入备份的考评组指标信息
				resultTagetLibService.insertResultTagetLibs(resultTagetLibs);
			}




			//下面初始化lz_flow流程表 lz_flow_approval_role流程审批表
			List<FlowApprovalRole> flowApprovalRoles = new ArrayList<>();
			int stepIndex = 0;
			for (FlowChartDetailRecord flowChartDetailRecord:flowChartDetailRecords
			) {
				Flow flow = new Flow();
				flow.setFlowId(evaluationGroup.getId());
				flow.setOpt("+");
				flow.setStartId(flowStart.getId());
				flow.setChartId(flowChartDetailRecord.getChartId());
				flow.setOptDesc(chartNameMaps.get(flowChartDetailRecord.getChartId()));

				flowService.insertFlow(flow);
				FlowApprovalRole flowApprovalRole = null;
				if(flowChartDetailRecord.getOptType().intValue() == ChartOptType.APPOINT.getCode()){//指定人员的
					String[] optIds = flowChartDetailRecord.getOptIds().split(",");
					for (String id:optIds
					) {

						flowApprovalRole = new FlowApprovalRole();
						flowApprovalRole.setFlowId(flow.getId());
						flowApprovalRole.setApprovalId(Long.parseLong(id));
						flowApprovalRole.setStepType(flowChartDetailRecord.getStepType());
						flowApprovalRole.setRoleId(flowChartDetailRecord.getRoleIds());
						flowApprovalRole.setType(flowChartDetailRecord.getOptType());
						flowApprovalRoles.add(flowApprovalRole);
						flowApprovalRole.setStepIndex(stepIndex);
						if(flowChartDetailRecord.getStepType().intValue() == 0){
							//依次
							stepIndex++;
						}
					}
					//stepIndex++;
					if(flowApprovalRole != null){
						stepIndex = flowApprovalRole.getStepIndex() + 1;
					}

				}else{
					flowApprovalRole = new FlowApprovalRole();
					flowApprovalRole.setFlowId(flow.getId());
					flowApprovalRole.setStepType(flowChartDetailRecord.getStepType());
					flowApprovalRole.setRoleId(flowChartDetailRecord.getRoleIds());
					flowApprovalRole.setType(flowChartDetailRecord.getOptType());
					flowApprovalRoles.add(flowApprovalRole);
					flowApprovalRole.setStepIndex(stepIndex);

					stepIndex++;
				}

			}
			//插入记录
			if(flowApprovalRoles.size() > 0){
				flowApprovalRoleService.insertFlowApprovalRoles(flowApprovalRoles);

				//初始化lz_result_details数据
				List<ResultDetail> resultDetails = new ArrayList<>();


				List<EvaluationStartStaff> evaluationStartStaffs = new ArrayList<>();

				//下面初始化管理人员对应关系
				for (StaffEntity entity:staffManagers
				) {
					EvaluationStartStaff evaluationStartStaff = new EvaluationStartStaff();
					evaluationStartStaff.setEvaluationId(evaluationGroup.getId());
					evaluationStartStaff.setEvaluationName(evaluationGroup.getName());
					evaluationStartStaff.setStaffId(entity.getId());
					evaluationStartStaff.setStartId(flowStart.getId());
					evaluationStartStaff.setType(CheckStaffType.MANAGER.getCode());
					evaluationStartStaffs.add(evaluationStartStaff);

				}


				//下面初始化参与人员
				for (StaffSimpleInfo staffInfo:staffIds
				) {
					EvaluationStartStaff evaluationStartStaff = new EvaluationStartStaff();
					evaluationStartStaff.setEvaluationId(evaluationGroup.getId());
					evaluationStartStaff.setEvaluationName(evaluationGroup.getName());
					evaluationStartStaff.setStaffId(staffInfo.getId());
					evaluationStartStaff.setStartId(flowStart.getId());
					evaluationStartStaff.setType(CheckStaffType.STAFF.getCode());
					evaluationStartStaffs.add(evaluationStartStaff);


					//初始化lz_result_records数据
					ResultRecord resultRecord = new ResultRecord();
					resultRecord.setDepartmentId(staffInfo.getDepartmentId());
					resultRecord.setDepartmentName(staffInfo.getDepartmentName());
					resultRecord.setStaffId(staffInfo.getId());
					resultRecord.setStaffName(staffInfo.getName());
					resultRecord.setType(1);//设置为提交目标
					resultRecord.setStatus(0);//设置为新建
					resultRecord.setStartId(flowStart.getId());
					resultRecord.setEvaluationId(evaluationGroup.getId());
					resultRecord.setFlowProcess(0);//设置为目标制定

					//下面初始化flow_staff_id_role字段，步骤为0的
					String roleJSON = "[";
					for (int i = 0; i < flowApprovalRoles.size() ;i++){
						FlowApprovalRole approvalRole = flowApprovalRoles.get(i);
						if(approvalRole.getStepIndex().intValue() == 0){//找到所有步骤为0的人员
							Long staffId = approvalRole.getApprovalId();//默认为指定人员。
							if(approvalRole.getType().intValue() == ChartOptType.SELF.getCode()){
								//制定人员为自己的
								staffId = staffInfo.getId();
								if(i == 0){//目前只设置一个，多个不明确是否支持，roleJSON是支持多个的
									//设置当前审批员工id current_approval_staff_id
									resultRecord.setCurrentApprovalStaffId(staffInfo.getId());
									//设置当前审批员工姓名 current_approval_staff_name
									resultRecord.setCurrentApprovalStaffName(staffInfo.getName());

								}
							} else if(approvalRole.getType().intValue() > 0){//当设置为几级领导时
								///查找领导，如果不存在那么设置管理人员
								List<StaffEntity> staffLeader;
								String key = staffInfo.getDepartmentId() + approvalRole.getType();
								if(staffManages.containsKey(key)){
									staffLeader = staffManages.get(staffInfo.getDepartmentId());
								}else{
									DepartManagers departManagers =
											staffService.findLeader(staffInfo.getId(), approvalRole.getType());
									staffLeader = departManagers.getManagers();
									staffManages.put(key, departManagers.getManagers());
								}

								if(staffLeader.size() == 0){
									//没有领导，通知到组设置的绩效管理人员
									for (StaffEntity entity:staffManagers
									) {
										roleJSON += ("{\"roleId\":0,\"staffId\":" + entity.getId() + "},");//这里写死了权限为0的即为找不到领导

									}
									if(i == 0){//目前只设置一个，多个不明确是否支持，roleJSON是支持多个的
										//设置当前审批员工id current_approval_staff_id
										resultRecord.setCurrentApprovalStaffId(staffManagers.get(0).getId());
										//设置当前审批员工姓名 current_approval_staff_name
										resultRecord.setCurrentApprovalStaffName(staffManagers.get(0).getName());

									}
								}else{
									for(int j = 0; j <staffLeader.size(); j++ ){
										StaffEntity staff = staffLeader.get(j);

										roleJSON += ("{\"roleId\":"+ approvalRole.getRoleId() +
												",\"staffId\":" + staff.getId() + "},");
									}
									if(i == 0){//目前只设置一个，多个不明确是否支持，roleJSON是支持多个的
										//设置当前审批员工id current_approval_staff_id
										resultRecord.setCurrentApprovalStaffId(staffLeader.get(0).getId());
										//设置当前审批员工姓名 current_approval_staff_name
										resultRecord.setCurrentApprovalStaffName(staffLeader.get(0).getName());

									}
								}

								continue;
							}else{
								if(i == 0){//目前只设置一个，多个不明确是否支持，roleJSON是支持多个的
									//设置当前审批员工id current_approval_staff_id
									resultRecord.setCurrentApprovalStaffId(approvalRole.getApprovalId());
									//设置当前审批员工姓名 current_approval_staff_name
									resultRecord.setCurrentApprovalStaffName("");

								}
							}

							roleJSON += ("{\"roleId\":"+ approvalRole.getRoleId() +
									",\"staffId\":" + staffId + "},");
							continue;
						}
						break;
					}
					roleJSON += "]";
					roleJSON = roleJSON.replace(",]", "]");
					resultRecord.setFlowStaffIdRole(roleJSON);
					resultRecordService.insertResultRecord(resultRecord);
					//下面生成实际的考核流程
					resultRecordService.initFlowRecord(resultRecord.getId());
					//下面生成ResultDetail对象
					for (ResultModelDto modelDto:resultModelDtos
					) {


						if(modelDto.getTagetLibs() != null && modelDto.getTagetLibs().size() > 0){//模板里面有添加指标
							for (ResultTagetLibDto libDto:
									modelDto.getTagetLibs()) {


								ResultDetail resultDetail = new ResultDetail();
								resultDetail.setRecordId(resultRecord.getId());
								resultDetail.setTarget(libDto.getName());
								resultDetail.setType(modelDto.getType());
								resultDetail.setKeyResult(libDto.getKeyResult());
								resultDetail.setCheckWeight(libDto.getWeight());
								resultDetail.setStaffId(staffInfo.getId());
								resultDetail.setPriority(libDto.getOrderBy());
								resultDetails.add(resultDetail);
							}
						}
					}
				}
				//如果有数据插入lz_result_detail表
				if(resultDetails.size() > 0){
					//
					resultDetailService.insertResultDetails(resultDetails);

				}



				evaluationStartStaffService.insertEvaluationStartStaffs(evaluationStartStaffs);
				//下面通知所有参与考核人员

				//如果有下面通知所有管理人员
			}else{
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//事务回滚
				return R.error(evaluationGroup.getName() + "——初始化考核流程失败");
			}

		}
		return R.ok("发起成功");
	}

	@Override
	public R getModelById(Long id, int type){
		/*EvaluationGroup evaluationGroup = evaluationGroupService.selectEvaluationGroupById(id);
         List<StaffSimpleInfo> staffIds = evaluationGroupService.selectAllStaffSimpleInfoByGroupId(evaluationGroup);*/
		//flowStart = flowStartService.selectFlowStartById(flowStart.getId());
		DepartManagers staffEntity = staffService.findLeader(id, type);
		return R.ok().put("data",staffEntity);
	}


}
