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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.security.common.Constant;
import org.security.common.eum.ProjectNodeEnum;
import org.security.ht.vo.basic.EmployeeVO;
import org.security.trans.dataStatistics.dto.StatisticsDataDTO;
import org.security.trans.dataStatistics.service.ProjectDataService;
import org.security.trans.dataStatistics.vo.HistogramDataVO;
import org.security.trans.dataStatistics.vo.PieChartDataVO;
import org.security.trans.projectBudgetManagement.entity.Project;
import org.security.trans.projectBudgetManagement.entity.ProjectContract;
import org.security.trans.projectBudgetManagement.entity.ProjectPayPlan;
import org.security.trans.projectBudgetManagement.service.IProjectContractService;
import org.security.trans.projectBudgetManagement.service.IProjectPayPlanService;
import org.security.trans.projectBudgetManagement.service.IProjectService;
import org.security.trans.projectBudgetManagement.vo.ProjectVO;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ：wzf
 * @apiNote ：项目管理数据统计
 * @since ：Created in 2022/12/2 15:24
 */
@Service
@Slf4j
@AllArgsConstructor
public class ProjectDataServiceImpl implements ProjectDataService {

	private final IProjectService projectService;
	private final IProjectContractService projectContractService;
	private final IProjectPayPlanService projectPayPlanService;
	private final InspectionDataServiceImpl inspectionDataService;


	@Override
	public List<PieChartDataVO> getProjectTypeData(StatisticsDataDTO statisticsDataDTO) {
		ArrayList<PieChartDataVO> vos = new ArrayList<>();
		List<Project> list = getProjectsAimData(statisticsDataDTO);
		if (Func.isNotEmpty(list)) {
			Map<String, List<Project>> collect = list.stream().filter(item -> Func.isNotEmpty(item.getProjectType())).collect(Collectors.groupingBy(Project::getProjectType));
			if (Func.isNotEmpty(collect)) {
				collect.forEach((key, value) -> {
					setPieChartResultData(vos, key, value);
				});
			}
		}
		return vos;
	}

	@Override
	public List<HistogramDataVO> getProjectNodeData(StatisticsDataDTO statisticsDataDTO) {
		ArrayList<HistogramDataVO> vos = new ArrayList<>();
		List<Project> list = getProjectsAimData(statisticsDataDTO);
		if (Func.isNotEmpty(list)) {
			Map<String, List<Project>> collect = list.stream().filter(item -> Func.isNotEmpty(item.getProjectStatus())).collect(Collectors.groupingBy(Project::getProjectStatus));
			if (Func.isNotEmpty(collect)) {
				collect.forEach((key, value) -> {
					HistogramDataVO vo = new HistogramDataVO();
					vo.setName(ProjectNodeEnum.parseByCode(Integer.valueOf(key)).getLabel());
					vo.setValue(Func.isNotEmpty(value) ? value.size() : 0);
					vos.add(vo);
				});
			}
		}
		return vos;
	}

	@Override
	public List<PieChartDataVO> getConcatAmtData(StatisticsDataDTO statisticsDataDTO) {
		ArrayList<PieChartDataVO> vos = new ArrayList<>();
		List<Project> list = getProjectsAimData(statisticsDataDTO);
		if (Func.isNotEmpty(list)) {
			List<ProjectVO> projectVOList = Func.copy(list, ProjectVO.class);
			//项目合同总金额计算
			setConcatAmt(projectVOList);
			List<ProjectVO> collect = projectVOList.stream().filter(item -> Func.isNotEmpty(item.getConcatAmtTotal()) && item.getConcatAmtTotal().compareTo(new BigDecimal(10)) < 0).collect(Collectors.toList());
			setPieData(vos, collect);
			List<ProjectVO> collect1 = projectVOList.stream().filter(item -> Func.isNotEmpty(item.getConcatAmtTotal()) && item.getConcatAmtTotal().compareTo(new BigDecimal(10)) >= 0 && item.getConcatAmtTotal().compareTo(new BigDecimal(50)) < 0).collect(Collectors.toList());
			setPieData(vos, collect1);
			List<ProjectVO> collect2 = projectVOList.stream().filter(item -> Func.isNotEmpty(item.getConcatAmtTotal()) && item.getConcatAmtTotal().compareTo(new BigDecimal(50)) >= 0 && item.getConcatAmtTotal().compareTo(new BigDecimal(100)) < 0).collect(Collectors.toList());
			setPieData(vos, collect2);
			List<ProjectVO> collect3 = projectVOList.stream().filter(item -> Func.isNotEmpty(item.getConcatAmtTotal()) && item.getConcatAmtTotal().compareTo(new BigDecimal(100)) >= 0 && item.getConcatAmtTotal().compareTo(new BigDecimal(200)) < 0).collect(Collectors.toList());
			setPieData(vos, collect3);
			List<ProjectVO> collect4 = projectVOList.stream().filter(item -> Func.isNotEmpty(item.getConcatAmtTotal()) && item.getConcatAmtTotal().compareTo(new BigDecimal(200)) >= 0).collect(Collectors.toList());
			setPieData(vos, collect4);
		}
		return vos;
	}

	/**
	 * 合同金额分布饼图赋值
	 */
	private void setPieData(ArrayList<PieChartDataVO> vos, List<ProjectVO> collect) {
		if (Func.isNotEmpty(collect)) {
			PieChartDataVO vo = new PieChartDataVO();
			vo.setName("[0,10)");
			vo.setValue(Func.isNotEmpty(collect) ? collect.size() : 0);
			vos.add(vo);
		}
	}


	/**
	 * 项目合同总金额计算
	 */
	private void setConcatAmt(List<ProjectVO> projectVOList) {
		projectVOList.forEach(item -> {
			List<ProjectContract> contractList = projectContractService.list(new QueryWrapper<ProjectContract>().lambda().eq(Func.isNotEmpty(item.getId()), ProjectContract::getProjectLinkId, item.getId()));
			if (Func.isNotEmpty(contractList)) {
				BigDecimal concatAmt = contractList.stream().filter(concat -> Func.isNotEmpty(concat.getContractAmt())).map(ProjectContract::getContractAmt).reduce(BigDecimal.ZERO, BigDecimal::add);
				item.setConcatAmtTotal(concatAmt);
			}
		});
	}

	@Override
	public List<PieChartDataVO> getPayData(StatisticsDataDTO statisticsDataDTO) {
		ArrayList<PieChartDataVO> vos = new ArrayList<>();
		List<Project> list = getProjectsAimData(statisticsDataDTO);
		if (Func.isNotEmpty(list)) {
			//统计基础值计算赋值
			List<ProjectVO> projectVOList = setBaseData(list);
			//筛选出支付完成的项目
			setPayPlanData(vos, projectVOList, 1, "支付完成");
			//筛选出支付未完成-仅质保金待付的项目
			setPayPlanData(vos, projectVOList, 2, "仅质保金待付");
			//筛选出支付未完成-其他待付的项目
			setPayPlanData(vos, projectVOList, 3, "其他待付");
		}
		return vos;
	}

	/**
	 * 统计基础值计算赋值
	 */
	private List<ProjectVO> setBaseData(List<Project> list) {
		List<ProjectVO> projectVOList = Func.copy(list, ProjectVO.class);
		projectVOList.forEach(item -> {
			List<ProjectPayPlan> plans = projectPayPlanService.list(new QueryWrapper<ProjectPayPlan>().lambda().eq(Func.isNotEmpty(item.getId()), ProjectPayPlan::getProjectLinkId, item.getId()));
			//项目支付计划为空，则该项目为未支付完成-其他
			if (Func.isEmpty(plans) || plans.size() == 0) {
				item.setPayStatus(3);
			}//项目支付及化不为空，
			else {
				//筛选出实际支付金额小于计划支付金额的支付计划
				List<ProjectPayPlan> collect = plans.stream().filter(plan -> Func.isNotEmpty(plan.getActualAmt())
					&& Func.isNotEmpty(plan.getPlanAmt())
					&& plan.getActualAmt().compareTo(plan.getPlanAmt()) < 0).collect(Collectors.toList());
				//实际支付金额大于等于计划支付金额，该项目为支付完成状态的项目
				if (Func.isEmpty(collect) && collect.size() <= 0) {
					item.setPayStatus(1);
				} else {
					//若项目付款计划的未支付完成记录中含有一条其他付款计划，则该项目归属于其他待付，反之则为仅质保金待付
					List<ProjectPayPlan> collect1 = collect.stream().filter(item1 -> Func.isNotEmpty(item1.getType()) && item1.getType().equals(Constant.PROJECT_PAY_PLAN_TWO)).collect(Collectors.toList());
					item.setPayStatus((Func.isNotEmpty(collect1) && collect1.size() > 0) ? 3 : 2);
				}

			}
		});
		return projectVOList;
	}

	/**
	 * 付款计划饼图分类赋值
	 */
	private void setPayPlanData(ArrayList<PieChartDataVO> vos, List<ProjectVO> projectVOList, int payStatus, String aimName) {
		List<ProjectVO> voList = projectVOList.stream().filter(item -> item.getPayStatus() == payStatus).collect(Collectors.toList());
		PieChartDataVO vo = new PieChartDataVO();
		vo.setName(aimName);
		vo.setValue(Func.isNotEmpty(voList) ? voList.size() : 0);
		vos.add(vo);
	}


	/**
	 * 获取项目主表统计数据
	 */
	private List<Project> getProjectsAimData(StatisticsDataDTO statisticsDataDTO) {
		List<String> aimDepts = inspectionDataService.setDeptIds(statisticsDataDTO.getDeptId(), statisticsDataDTO.getIncludeChildren());
		return projectService.list(new QueryWrapper<Project>().lambda().eq(Project::getState, Constant.SUBMIT_TYPE_ONE).in(Func.isNotEmpty(aimDepts), Project::getDeptId, aimDepts));
	}

	/**
	 * 封装饼图返回结果
	 */
	private void setPieChartResultData(List<PieChartDataVO> vos, String key, List<Project> value) {
		PieChartDataVO vo = new PieChartDataVO();
		vo.setName("1".equals(key) ? "建设类" : "服务类");
		vo.setValue(Func.isNotEmpty(value) ? value.size() : 0);
		vos.add(vo);
	}
}
