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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.precontrol.common.dto.StatisticsDto;
import com.yeejoin.precontrol.common.entity.Company;
import com.yeejoin.precontrol.common.entity.Project;
import com.yeejoin.precontrol.common.entity.ProjectCompany;
import com.yeejoin.precontrol.common.entity.ProjectCompanyFilling;
import com.yeejoin.precontrol.common.entity.TaskPerson;
import com.yeejoin.precontrol.common.entity.TaskSalaryConfirm;
import com.yeejoin.precontrol.common.enums.TaskPersonTypeEnum;
import com.yeejoin.precontrol.common.mapper.ProjectCompanyFillingMapper;
import com.yeejoin.precontrol.common.mapper.StatisticsMapper;
import com.yeejoin.precontrol.common.service.ICompanyService;
import com.yeejoin.precontrol.common.service.IProjectCompanyFillingService;
import com.yeejoin.precontrol.common.service.IProjectCompanyService;
import com.yeejoin.precontrol.common.service.IProjectService;
import com.yeejoin.precontrol.common.service.ITaskPersonService;
import com.yeejoin.precontrol.common.service.ITaskSalaryConfirmService;
import com.yeejoin.precontrol.common.utils.UUIDUtils;
import com.yeejoin.precontrol.common.vo.ProjectCompanyFillingVo;

import lombok.Data;

/**
 * 项目关联分包商表 服务实现类
 *
 * @author duanwei
 * @date 2022-06-08
 */
@Service
public class ProjectCompanyFillingServiceImpl extends ServiceImpl<ProjectCompanyFillingMapper, ProjectCompanyFilling>
		implements IProjectCompanyFillingService {

	@Autowired
	IProjectService iProjectService;

	@Autowired
	ICompanyService iCompanyService;

	@Autowired
	IProjectCompanyService iProjectCompanyService;

	@Autowired
	ITaskSalaryConfirmService iTaskSalaryConfirmService;

	@Autowired
	ITaskPersonService iTaskPersonService;

	@Autowired
	StatisticsMapper statisticsMapper;

	@Override
	public List<ProjectCompanyFillingVo> list(String orgCode, Date startMonth, Date endMonth,
			ProjectCompanyFillingVo projectCompanyFillingParam) {
		List<ProjectCompanyFillingVo> list = new ArrayList<ProjectCompanyFillingVo>();
		List<Project> projects = new ArrayList<Project>();
		if (orgCode != null) {
			projects = iProjectService.list(new LambdaQueryWrapper<Project>().like(Project::getOrgCode, orgCode));
		} else {
			projects = iProjectService.list();
		}
		List<Long> pIds = projects.stream().map(i -> i.getId()).collect(Collectors.toList());
		if (pIds.size() == 0) {
			return list;
		}
		long index = 0;
		int allpersonCount = 0, allpayCount = 0;
		double alltotalSalary = 0, allactualSalary = 0, alldifferenceSalary = 0, allendowmentInsurance = 0,
				allmedicalInsurance = 0, allinjuryInsurance = 0, allotherAmounts = 0;
		if (orgCode == null) {
			for (Project project : projects) {
				List<ProjectCompany> pcs = iProjectCompanyService.list(
						new LambdaQueryWrapper<ProjectCompany>().eq(ProjectCompany::getProjectId, project.getId()));
				int personCount = 0, payCount = 0;
				double totalSalary = 0.0, actualSalary = 0.0, endowmentInsurance = 0.0, medicalInsurance = 0.0,
						injuryInsurance = 0.0, otherAmounts = 0.0;
				for (ProjectCompany projectCompany : pcs) {
					List<TaskSalaryConfirm> taskSalaryConfirms = iTaskSalaryConfirmService
							.list(new LambdaQueryWrapper<TaskSalaryConfirm>()
									.eq(TaskSalaryConfirm::getProjectId, projectCompany.getProjectId())
									.eq(TaskSalaryConfirm::getCompanyId, projectCompany.getCompanyId())
									.apply("MONTH(create_date) between MONTH({0}) and MONTH({1})", startMonth,
											endMonth));
					StatisticsDto statisticsDto = new StatisticsDto(null, projectCompany.getProjectId(),
							projectCompany.getCompanyId());
					personCount += statisticsMapper.companyPersonCount(statisticsDto, null, null, null, false);
					for (TaskSalaryConfirm taskSalaryConfirm : taskSalaryConfirms) {
						payCount += iTaskPersonService.count(new LambdaQueryWrapper<TaskPerson>()
								.eq(TaskPerson::getTaskId, taskSalaryConfirm.getTaskId())
								.ne(TaskPerson::getType, TaskPersonTypeEnum.CREATEPERSON.getValue()));
						totalSalary += Double.valueOf(String.valueOf(taskSalaryConfirm.getContractTotalSalary()));
						actualSalary += Double.valueOf(String.valueOf(taskSalaryConfirm.getCurrentPaySalary()));
					}
					List<ProjectCompanyFilling> filllist = this.list(new LambdaQueryWrapper<ProjectCompanyFilling>()
							.eq(ProjectCompanyFilling::getProjectId, projectCompany.getProjectId())
							.eq(ProjectCompanyFilling::getCompanyId, projectCompany.getCompanyId())
							.apply("MONTH(fill_month) between MONTH({0}) and MONTH({1})", startMonth, endMonth));
					for (ProjectCompanyFilling projectCompanyFilling : filllist) {
						endowmentInsurance += projectCompanyFilling.getEndowmentInsurance();
						medicalInsurance += projectCompanyFilling.getMedicalInsurance();
						injuryInsurance += projectCompanyFilling.getInjuryInsurance();
						otherAmounts += projectCompanyFilling.getOtherAmounts();
					}
				}
				double differenceSalary = totalSalary - actualSalary;
				ProjectCompanyFillingVo projectCompanyFillingVo = new ProjectCompanyFillingVo();
				projectCompanyFillingVo.setId(++index);
				projectCompanyFillingVo.setProjectId(project.getId());
				projectCompanyFillingVo.setProjectName(project != null ? project.getName() : null);
				projectCompanyFillingVo.setFillMonth(startMonth);
				projectCompanyFillingVo.setPersonCount(personCount);
				allpersonCount += personCount;
				projectCompanyFillingVo.setPayCount(payCount);
				allpayCount += payCount;
				projectCompanyFillingVo.setTotalSalary(totalSalary);
				alltotalSalary += totalSalary;
				projectCompanyFillingVo.setActualSalary(actualSalary);
				allactualSalary += actualSalary;
				projectCompanyFillingVo.setDifferentSalary(differenceSalary);
				alldifferenceSalary += differenceSalary;
				projectCompanyFillingVo.setEndowmentInsurance(endowmentInsurance);
				allendowmentInsurance+=endowmentInsurance;
				projectCompanyFillingVo.setMedicalInsurance(medicalInsurance);
				allmedicalInsurance+=medicalInsurance;
				projectCompanyFillingVo.setInjuryInsurance(injuryInsurance);
				allinjuryInsurance+=injuryInsurance;
				projectCompanyFillingVo.setOtherAmounts(otherAmounts);
				allotherAmounts+=otherAmounts;
				list.add(projectCompanyFillingVo);
			}
		} else {
			List<ProjectCompany> pcs = iProjectCompanyService
					.list(new LambdaQueryWrapper<ProjectCompany>().in(ProjectCompany::getProjectId, pIds));
			for (ProjectCompany projectCompany : pcs) {
				List<TaskSalaryConfirm> taskSalaryConfirms = iTaskSalaryConfirmService
						.list(new LambdaQueryWrapper<TaskSalaryConfirm>()
								.eq(TaskSalaryConfirm::getProjectId, projectCompany.getProjectId())
								.eq(TaskSalaryConfirm::getCompanyId, projectCompany.getCompanyId())
								.apply("MONTH(create_date) between MONTH({0}) and MONTH({1})", startMonth, endMonth));
				StatisticsDto statisticsDto = new StatisticsDto(null, projectCompany.getProjectId(),
						projectCompany.getCompanyId());
				int personCount = statisticsMapper.companyPersonCount(statisticsDto, null, null, null, false);
				int payCount = 0;
				double totalSalary = 0.0, actualSalary = 0.0, endowmentInsurance = 0.0, medicalInsurance = 0.0,
						injuryInsurance = 0.0, otherAmounts = 0.0;
				for (TaskSalaryConfirm taskSalaryConfirm : taskSalaryConfirms) {
					payCount += iTaskPersonService.count(new LambdaQueryWrapper<TaskPerson>()
							.eq(TaskPerson::getTaskId, taskSalaryConfirm.getTaskId())
							.ne(TaskPerson::getType, TaskPersonTypeEnum.CREATEPERSON.getValue()));
					totalSalary += Double.valueOf(String.valueOf(taskSalaryConfirm.getContractTotalSalary()));
					actualSalary += Double.valueOf(String.valueOf(taskSalaryConfirm.getCurrentPaySalary()));
				}
				List<ProjectCompanyFilling> filllist = this.list(new LambdaQueryWrapper<ProjectCompanyFilling>()
						.eq(ProjectCompanyFilling::getProjectId, projectCompany.getProjectId())
						.eq(ProjectCompanyFilling::getCompanyId, projectCompany.getCompanyId())
						.apply("MONTH(fill_month) between MONTH({0}) and MONTH({1})", startMonth, endMonth));
				for (ProjectCompanyFilling projectCompanyFilling : filllist) {
					endowmentInsurance += projectCompanyFilling.getEndowmentInsurance();
					medicalInsurance += projectCompanyFilling.getMedicalInsurance();
					injuryInsurance += projectCompanyFilling.getInjuryInsurance();
					otherAmounts += projectCompanyFilling.getOtherAmounts();
				}
				double differenceSalary = totalSalary - actualSalary;
				ProjectCompanyFillingVo projectCompanyFillingVo = new ProjectCompanyFillingVo();
				projectCompanyFillingVo.setId(filllist.size()>0&&filllist.get(0)!=null?filllist.get(0).getId():index++);
				projectCompanyFillingVo.setProjectId(projectCompany.getProjectId());
				projectCompanyFillingVo.setCompanyId(projectCompany.getCompanyId());
				Project project = iProjectService.getById(projectCompany.getProjectId());
				projectCompanyFillingVo.setProjectName(project != null ? project.getName() : null);
				Company company = iCompanyService.getById(projectCompany.getCompanyId());
				projectCompanyFillingVo.setCompanyName(company != null ? company.getName() : null);
				projectCompanyFillingVo.setFillMonth(startMonth);
				projectCompanyFillingVo.setPersonCount(personCount);
				allpersonCount += personCount;
				projectCompanyFillingVo.setPayCount(payCount);
				allpayCount += payCount;
				projectCompanyFillingVo.setTotalSalary(totalSalary);
				alltotalSalary += totalSalary;
				projectCompanyFillingVo.setActualSalary(actualSalary);
				allactualSalary += actualSalary;
				projectCompanyFillingVo.setDifferentSalary(differenceSalary);
				alldifferenceSalary += differenceSalary;
				projectCompanyFillingVo.setEndowmentInsurance(endowmentInsurance);
				allendowmentInsurance+=endowmentInsurance;
				projectCompanyFillingVo.setMedicalInsurance(medicalInsurance);
				allmedicalInsurance+=medicalInsurance;
				projectCompanyFillingVo.setInjuryInsurance(injuryInsurance);
				allinjuryInsurance+=injuryInsurance;
				projectCompanyFillingVo.setOtherAmounts(otherAmounts);
				allotherAmounts+=otherAmounts;
				list.add(projectCompanyFillingVo);
			}
		}

		ProjectCompanyFillingVo projectCompanyFillingVo = new ProjectCompanyFillingVo();
		projectCompanyFillingVo.setPersonCount(allpersonCount);
		projectCompanyFillingVo.setPayCount(allpayCount);
		projectCompanyFillingVo.setTotalSalary(alltotalSalary);
		projectCompanyFillingVo.setActualSalary(allactualSalary);
		projectCompanyFillingVo.setDifferentSalary(alldifferenceSalary);
		projectCompanyFillingVo.setEndowmentInsurance(allendowmentInsurance);
		projectCompanyFillingVo.setMedicalInsurance(allmedicalInsurance);
		projectCompanyFillingVo.setInjuryInsurance(allinjuryInsurance);
		projectCompanyFillingVo.setOtherAmounts(allotherAmounts);
		list.add(projectCompanyFillingVo);
		return list;
	}

	@Override
	public boolean save(List<ProjectCompanyFillingVo> projectCompanyFillings, Long personId) {
		List<ProjectCompanyFilling> list = new ArrayList<ProjectCompanyFilling>();
		for (ProjectCompanyFillingVo projectCompanyFillingVo : projectCompanyFillings) {
			ProjectCompanyFilling projectCompanyFilling = new ProjectCompanyFilling();
			BeanUtils.copyProperties(projectCompanyFillingVo, projectCompanyFilling);
			projectCompanyFilling.setFillPersonId(personId);
			list.add(projectCompanyFilling);
		}
		this.saveOrUpdateBatch(list);
		return true;
	}

}
