/*
 *      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.assessment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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.ht.entity.basic.Department;
import org.security.system.feign.ISysClient;
import org.security.trans.assessment.entity.Assessment;
import org.security.trans.assessment.entity.AssessmentDetail;
import org.security.trans.assessment.mapper.AssessmentMapper;
import org.security.trans.assessment.service.IAssessmentDetailService;
import org.security.trans.assessment.service.IAssessmentService;
import org.security.trans.assessment.vo.AssessmentDetailVO;
import org.security.trans.assessment.vo.AssessmentVO;
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.AssessmentDataDTO;
import org.security.trans.dataStatistics.vo.AssessmentDataVO;
import org.security.trans.dataStatistics.vo.RiskDataVO;
import org.security.trans.outsourcing.service.IOutCompanyService;
import org.security.trans.projectBudgetManagement.service.IProjectService;
import org.security.trans.projectBudgetManagement.vo.ProjectVO;
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.Func;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 考核评价信息记录表 服务实现类
 *
 * @author BladeX
 * @since 2022-07-05
 */
@AllArgsConstructor
@Service
@Slf4j
public class AssessmentServiceImpl extends ServiceImpl<AssessmentMapper, Assessment> implements IAssessmentService {

	private final IAssessmentDetailService assessmentDetailService;
	private final IFileService fileService;
	private final IDepartmentService departmentService;
	private final IOutCompanyService outCompanyService;
	private final IProjectService projectService;
	private final IFlowClient flowClient;
	private final ISysClient sysClient;

	@Override
	public IPage<AssessmentVO> getPage(IPage<AssessmentVO> page, AssessmentVO assessmentVO) {
		//获取登录机构作为考评方的数据
		List<AssessmentVO> list = baseMapper.getData(assessmentVO);
		//获取当前登录机构作为被考评方，且处于考评结束节点的考评数据
		List<Assessment> assessments = this.list(new QueryWrapper<Assessment>().lambda().eq(Assessment::getDelFlag, Constant.DELETE_FLAG_0)
			.eq(Assessment::getState, Constant.HANDIN_STATE_FINISH)
			.eq(Func.isNotEmpty(assessmentVO.getType()),Assessment::getType,assessmentVO.getType())
			.eq(Assessment::getEvaluated, AuthUtil.getDeptId()));
		List<AssessmentVO> assessmentVOList = Func.copy(assessments, AssessmentVO.class);
		list.addAll(assessmentVOList);
		ArrayList<AssessmentVO> vos = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Assessment::getId))), ArrayList::new));
		vos.forEach(this::setReturnResult);
		IPage<AssessmentVO> res = new Page<>();
		res.setTotal(page.getTotal());
		res.setSize(page.getSize());
		res.setCurrent(page.getCurrent());
		List<AssessmentVO> collect = vos.stream().sorted(Comparator.comparing(AssessmentVO::getCreatedTime).reversed()).collect(Collectors.toList());
		res.setRecords(collect);
		return res;
	}
	/**
	 * 处理返回对象，根据id获取对应name值
	 */
	private void setReturnResult(AssessmentVO item) {
		//考评项目名称 项目考评需要查询项目name
		if ("5".equals(item.getAssessmentType()) && Func.isEmpty(item.getProjectName())) {
			item.setProjectName(projectService.getById(item.getProjectId()).getProjectName());
		}else if("4".equals(item.getAssessmentType()) && Func.isEmpty(item.getEvaluatedName())){
		//相关方考评，需查被考评公司名称
			item.setEvaluatedName(outCompanyService.getById(item.getEvaluated()).getOutCompanyName());
		}
	}

	@Override
	public R handIn(AssessmentVO assessmentVO) {
		R<Assessment> res = saveWithDetail(assessmentVO);
		if (!res.isSuccess()) {
			throw new ServiceException("保存失败！");
		}
		Assessment assessment = res.getData();

//		boolean b;
		//提交领导确认的考核评价主表记录入库
//		if (Func.isNotEmpty(assessment.getId())){
//			b = this.update(assessment, new UpdateWrapper<Assessment>().lambda().eq(Assessment::getId, assessment.getId()).eq(Assessment::getState, Constant.USUAL_STATE_FALSE));
//		}else {
//			b = this.save(assessment);
//		}
		// 啥都不改调用save或update会返回false，所以注释掉
		// if (!b) {
		//     return R.fail(400,"该考核记录已提交领导确认，请勿重复提交");
		// }

		//发起流程提报
		Kv variables = Kv.create().set(ProcessConstant.BUSINESS_ID_KEY, assessment.getId());
		String businessTable = FlowUtil.getBusinessTable(Assessment.class);
		R<Integer> deptCategory = sysClient.getDeptCategory(Long.valueOf(AuthUtil.getUser().getDeptId()));
		if (!deptCategory.isSuccess()) {
			throw new ServiceException("查询部门类型失败，请检查后再试！");
		}
		variables.set("deptCategory", deptCategory.getData());
		variables.set(ProcessConstant.START_PROC_USER_ID, AuthUtil.getUserId());
		String assessmentKey;
		switch (assessment.getAssessmentType()) {
			case "1":
				assessmentKey = ProcessConstant.BANK_ASSESSMENT_KEY;
				variables.set("selfAssessment", true);
				break;
			case "2":
				assessmentKey = ProcessConstant.BANK_ASSESSMENT_KEY;
				variables.set("selfAssessment", true);
				break;
			case "3":
				assessmentKey = ProcessConstant.BANK_ASSESSMENT_KEY;
				variables.set("selfAssessment", false);
				break;
			case "4":
				assessmentKey = ProcessConstant.OUTSOURCING_ASSESSMENT_KEY;
				// 是否是分行下发
				variables.set("branchStart", false);
				break;
			case "5":
				assessmentKey = ProcessConstant.PROJECT_ASSESSMENT_KEY;
				break;
			default:
				throw new ServiceException("不支持的考评类型");
		}

		R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(assessmentKey);
		if (definitionRes.isSuccess()) {
			assessment.setProcessDefinitionId(definitionRes.getData().getId());
		} else {
			throw new ServiceException("查询流程定义失败");
		}
		R<BladeFlow> result = flowClient.startProcessInstanceById(assessment.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(assessment.getId())), variables);
		if (result.isSuccess()) {
			log.debug("流程已启动,流程ID:" + result.getData().getProcessInstanceId());
			assessment.setProcessInstanceId(result.getData().getProcessInstanceId());
			assessment.setState(Constant.HANDIN_STATE_AUDIT);
		} else {
			throw new ServiceException("开启流程失败");
		}
		this.updateById(assessment);
		return R.success("提交成功");
	}

	@Override
	public List<AssessmentDataVO> getAimStatisticsData(AssessmentDataDTO assessmentDataDTO, List<String> aimDepts, List<String> aimType) {
		return baseMapper.getAimStatisticsData(assessmentDataDTO,aimDepts,aimType);
	}

	@Override
	public List<AssessmentDataVO> getProjectStatisticsData(AssessmentDataDTO assessmentDataDTO, List<String> aimType) {
		return baseMapper.getProjectStatisticsData(assessmentDataDTO,aimType);
	}

	@Override
	public AssessmentVO getDetail(AssessmentVO assessmentVO) {
		Assessment query = BeanUtil.copyProperties(assessmentVO, Assessment.class);
		QueryWrapper<Assessment> queryWrapper = Condition.getQueryWrapper(query);
		Assessment assessment = baseMapper.selectOne(queryWrapper);
		List<AssessmentDetailVO> detailVOS = assessmentDetailService.getByParentId(assessment.getId());
		AssessmentVO res = BeanUtil.copyProperties(assessment, AssessmentVO.class);
		this.setReturnResult(res);
		res.setDetails(detailVOS);
		res.setFileList(fileService.getAttachments(assessment.getId(),assessment.getGroupName()));
		return res;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R saveWithDetail(AssessmentVO assessmentVO) {
		Assessment assessment = BeanUtil.copyProperties(assessmentVO, Assessment.class);
		if(Func.isNull(assessment.getDeptId()) || Func.isBlank(assessment.getDeptId())){
			assessment.setDeptId(AuthUtil.getDeptId());
		}
		Department dep = departmentService.getById(assessment.getDeptId());
		assessment.setDeptName(Func.isNull(dep)?dep.getDeptName():"");
		List<AssessmentDetailVO> voDetails = assessmentVO.getDetails();
//		如果是机构考评，除加分项、扣分项之外的考评得分默认为考评总分；
//		如果是相关方考评和项目考评，除加分项、扣分项之外的考评得分为eva1--eva5的加总
		BigDecimal score = assessment.getTotalScore();
		if("4".equals(assessment.getAssessmentType()) || "5".equals(assessment.getAssessmentType())){
			score=assessment.getEva1().add(assessment.getEva2()).add(assessment.getEva3()).add(assessment.getEva4()).add(assessment.getEva5());
		}
		BigDecimal plusesScore = BigDecimal.ZERO;//加分项合计
		BigDecimal deductionScore = BigDecimal.ZERO;//扣分项合计
//		如果有加分、扣分明细，计算加分合计与扣分合计
		if(Func.isNotEmpty(voDetails)){
			for (AssessmentDetailVO voDetail : voDetails) {
				if ("1".equals(voDetail.getScoreType())) {
					plusesScore = plusesScore.add(voDetail.getScore());
				}
				if ("2".equals(voDetail.getScoreType())) {
					deductionScore = deductionScore.add(voDetail.getScore());
				}
			}
		}
		assessment.setPlusesScore(plusesScore);
		assessment.setState(Constant.USUAL_STATE_FALSE);
		assessment.setDeductionScore(deductionScore);
		//		计算最终得分 计算后最终结果不得超过考评总分
		BigDecimal tempScore = score.add(plusesScore).subtract(deductionScore);
		//被考评方名称赋值
		if (Func.isNotEmpty(assessment.getEvaluated())) {
//			被考评对象是行内机构
			if ("1".equals(assessment.getType())) {
				assessment.setEvaluatedName(departmentService.getById(assessment.getEvaluated()).getDeptName());
			}
//			被考评对象是相关方公司
			else if ("2".equals(assessment.getType())) {
				assessment.setEvaluatedName(outCompanyService.getById(assessment.getEvaluated()).getOutCompanyName());
			}
		}
		//项目考核被考评项目名称赋值
		if (Func.isNotEmpty(assessment.getProjectId())){
			assessment.setProjectName(projectService.getById(assessment.getProjectId()).getProjectName());
		}
		assessment.setFinalScore(tempScore.compareTo(assessmentVO.getFinalScore())==1?assessmentVO.getFinalScore():tempScore);
		this.saveOrUpdate(assessment);
		if(Func.isNotEmpty(voDetails)){
			List<AssessmentDetail> detailList = voDetails.stream().map(voDetail -> {
				AssessmentDetail assessmentDetail = BeanUtil.copyProperties(voDetail, AssessmentDetail.class);
				assessmentDetail.setParentId(assessment.getId());
				return assessmentDetail;
			}).collect(Collectors.toList());
			assessmentDetailService.saveOrUpdateBatch(detailList);
		}
		List<UploadVO> fileList = assessmentVO.getFileList();
		if (Objects.nonNull(fileList) && !fileList.isEmpty()) {
			fileService.saveAttachments(fileList, assessment.getId());
		}
		return R.data(assessment);
	}

}
