package com.ym.mec.biz.service.impl;

import com.ym.mec.biz.dal.dao.OperatingReportCloudDao;
import com.ym.mec.biz.dal.dao.OperatingReportNewDao;
import com.ym.mec.biz.dal.dao.VipGroupCategoryDao;
import com.ym.mec.biz.dal.entity.OperatingReportNew;
import com.ym.mec.biz.dal.entity.VipGroupCategory;
import com.ym.mec.biz.service.OperatingReportNewService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class OperatingReportNewServiceImpl extends BaseServiceImpl<Integer, OperatingReportNew>  implements OperatingReportNewService {
	
	@Autowired
	private OperatingReportNewDao operatingReportNewDao;
	@Autowired
	private VipGroupCategoryDao vipGroupCategoryDao;
	@Autowired
	private OperatingReportCloudDao operatingReportCloudDao;

	@Override
	public BaseDAO<Integer, OperatingReportNew> getDAO() {
		return operatingReportNewDao;
	}

    @Override
    public OperatingReportNewDao getDao() {
        return operatingReportNewDao;
    }

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void operatingReportMonth(Date month) {
		String firstDayOfMonth = DateUtil.dateToString(DateUtil.getFirstDayOfMonth(month),DateUtil.ISO_EXPANDED_DATE_FORMAT);
		String lastDayOfMonth = DateUtil.dateToString(DateUtil.getLastDayOfMonth(month),DateUtil.ISO_EXPANDED_DATE_FORMAT);
		String currentMonth = DateUtil.dateToString(DateUtil.getLastDayOfMonth(month),DateUtil.ISO_YEAR_MONTH_FORMAT);
		operatingReportNewDao.deleteByMonth(currentMonth);
		List<OperatingReportNew> operatingList = operatingReportNewDao.initOperatingReport(currentMonth);
		//更新团体云教练计费时间()
		operatingReportNewDao.initCloudStartTime(lastDayOfMonth);
		//标记缴费项目为已结算(已排课，并且在上个月有关联的课程)
		operatingReportCloudDao.settlementCalender(currentMonth);
		//标记当月结算的缴费项目(缴费项目结算后缴费、或者进行中加学员的都算当月结算)
		operatingReportCloudDao.settlementCurrentCalender(currentMonth);
		//销售收入、销售成本
		List<OperatingReportNew> sellList = operatingReportNewDao.sumSellAmount(currentMonth);
		Map<Integer, OperatingReportNew> collect = sellList.stream().collect(Collectors.groupingBy(OperatingReportNew::getOrganId,Collectors.collectingAndThen(Collectors.toList(),value->value.get(0))));
		//服务收入
		//导入的服务收入  (全部记录为课程收入)
		Map<Integer, BigDecimal> collect24 = MapUtil.convertIntegerMap(operatingReportNewDao.sumImportServerOrderAmount(currentMonth));
		//云教练赠送课程实际收入
		Map<Integer, BigDecimal> collect1 = MapUtil.convertIntegerMap(operatingReportNewDao.sumCloudCourseAmount(firstDayOfMonth,lastDayOfMonth));
		//亏损的云教练算到当月实际收入
		Map<Integer, BigDecimal> collect22 = MapUtil.convertIntegerMap(operatingReportNewDao.sumLossCloudAmount(currentMonth));
		//付费课程实际收入
		Map<Integer, BigDecimal> collect2 = MapUtil.convertIntegerMap(operatingReportNewDao.sumCourseAmount(firstDayOfMonth,lastDayOfMonth));

		//个人云教练当月收入
		Map<Integer, BigDecimal> collect3 = MapUtil.convertIntegerMap(operatingReportNewDao.sumPersonalCloudAmount(currentMonth,firstDayOfMonth,lastDayOfMonth));
		//团体云教练费用
		Map<Integer, BigDecimal> collect4 = MapUtil.convertIntegerMap(operatingReportNewDao.sumGroupCloudAmount(currentMonth,firstDayOfMonth,lastDayOfMonth));
		//团体云教练当月一次性结转
		Map<Integer, BigDecimal> collect5 = MapUtil.convertIntegerMap(operatingReportNewDao.sumGroupAmount(currentMonth));

		//乐保实收
		Map<Integer, BigDecimal> collect26 = MapUtil.convertIntegerMap(operatingReportNewDao.sumMaintenanceAmount(currentMonth));

		//业务退费
		Map<Integer, BigDecimal> collect6 = MapUtil.convertIntegerMap(operatingReportNewDao.sumRefundAmount(currentMonth));
		//变动费用
		Map<Integer, BigDecimal> collect7 = MapUtil.convertIntegerMap(operatingReportNewDao.sumVariableCosts(currentMonth));
		//固定费用
		Map<Integer, BigDecimal> collect8 = MapUtil.convertIntegerMap(operatingReportNewDao.sumFixedCosts(currentMonth));
		//内部结算
		Map<Integer, BigDecimal> collect18 = MapUtil.convertIntegerMap(operatingReportNewDao.sumInternalSettlement(currentMonth));

		//云教练预收款
		//个人云教练预收款
		Map<Integer, BigDecimal> collect9 = MapUtil.convertIntegerMap(operatingReportNewDao.sumCloudPreAmount(currentMonth,lastDayOfMonth));
		//团体云教练预收款
		Map<Integer, BigDecimal> collect10 = MapUtil.convertIntegerMap(operatingReportNewDao.sumGroupCloudPreAmount(currentMonth,lastDayOfMonth));
		//未生效云教练预收款
		Map<Integer, BigDecimal> collect25 = MapUtil.convertIntegerMap(operatingReportNewDao.sumWaitCloudPreAmount());
		//已排课但是课程未开始的云教练预收
		Map<Integer, BigDecimal> collect27 = MapUtil.convertIntegerMap(operatingReportNewDao.sumNotStartCloudPreAmount());

		//课程预收
		//云教练赠课预收
		Map<Integer, BigDecimal> collect11 = MapUtil.convertIntegerMap(operatingReportNewDao.sumCloudCoursePreAmount(lastDayOfMonth));
		//云教练赠送，未排课排课资格预收
		//获取categoryId
		VipGroupCategory category = vipGroupCategoryDao.getTheory();
		Map<Integer, BigDecimal> collect20 = MapUtil.convertIntegerMap(operatingReportNewDao.sumActivityUserMapperAmount(category.getId()));
		//付费课程预收
		Map<Integer, BigDecimal> collect12 = MapUtil.convertIntegerMap(operatingReportNewDao.sumCoursePreAmount(lastDayOfMonth));
		//付费团未排乐团课程预收（学员缴费）
		Map<Integer, BigDecimal> collect21 = MapUtil.convertIntegerMap(operatingReportNewDao.sumMusicCourseAmount());
		//排课资格预收
		Map<Integer, BigDecimal> collect23 = MapUtil.convertIntegerMap(operatingReportNewDao.sumSubActivityUserMapperAmount());

		//销售预收
		Map<Integer, BigDecimal> collect13 = MapUtil.convertIntegerMap(operatingReportNewDao.sumSalePreAmount());

		//其他预收
		Map<Integer, BigDecimal> collect14 = MapUtil.convertIntegerMap(operatingReportNewDao.sumOtherPreAmount());

		//预付款
		//房租
		Map<Integer, BigDecimal> collect19 = MapUtil.convertIntegerMap(operatingReportNewDao.sumPrepayments(currentMonth));

		//应收
		//欠费学员总金额
		Map<Integer, BigDecimal> collect15 = MapUtil.convertIntegerMap(operatingReportNewDao.sumArrearsAmount());
		//学校缴费订单待收款金额
		Map<Integer, BigDecimal> collect16 = MapUtil.convertIntegerMap(operatingReportNewDao.sumSchoolAmount());

		//应付（乐器押金）
		List<Map<Integer, BigDecimal>> maps = operatingReportNewDao.sumMusicMargin();
		Map<Integer, BigDecimal> collect17 = MapUtil.convertIntegerMap(maps);

		for (OperatingReportNew operatingReportNew : operatingList) {
			Integer organId = operatingReportNew.getOrganId();
			OperatingReportNew reportNew = collect.get(organId);
			if(Objects.nonNull(reportNew)){
				operatingReportNew.setSaleAmount(reportNew.getSaleAmount());
				operatingReportNew.setSaleCost(reportNew.getSaleCost());
			}

			operatingReportNew.setCourseAmount(getAmount(collect1.get(organId)));
			operatingReportNew.setCourseAmount(operatingReportNew.getCourseAmount().add(getAmount(collect2.get(organId))));
			operatingReportNew.setCourseAmount(operatingReportNew.getCourseAmount().add(getAmount(collect24.get(organId))));

			operatingReportNew.setCloudAmount(getAmount(collect3.get(organId)));
			operatingReportNew.setCloudAmount(operatingReportNew.getCloudAmount().add(getAmount(collect4.get(organId))));
			operatingReportNew.setCloudAmount(operatingReportNew.getCloudAmount().add(getAmount(collect5.get(organId))));
			operatingReportNew.setCloudAmount(operatingReportNew.getCloudAmount().add(getAmount(collect22.get(organId))));

			operatingReportNew.setMaintenanceAmount(getAmount(collect26.get(organId)));
			operatingReportNew.setBusinessRefund(getAmount(collect6.get(organId)));

			operatingReportNew.setServiceAmount(operatingReportNew.getCloudAmount().add(operatingReportNew.getCourseAmount()).add(operatingReportNew.getMaintenanceAmount()));
			operatingReportNew.setTotalIncome(operatingReportNew.getSaleAmount().add(operatingReportNew.getServiceAmount()).subtract(operatingReportNew.getBusinessRefund()));

			operatingReportNew.setInternalSettlement(getAmount(collect18.get(organId)));
			operatingReportNew.setFixedCosts(getAmount(collect7.get(organId)));
			operatingReportNew.setVariableCosts(getAmount(collect8.get(organId)));
			operatingReportNew.setTotalCost(operatingReportNew.getInternalSettlement().
					add(operatingReportNew.getFixedCosts()).add(operatingReportNew.getVariableCosts()));

			operatingReportNew.setCloudPrepaidFee(getAmount(collect9.get(organId)).
					add(getAmount(collect10.get(organId))).
					add(getAmount(collect27.get(organId))).
					add(getAmount(collect25.get(organId))));
			operatingReportNew.setCoursePrepaidFee(getAmount(collect11.get(organId)).add(getAmount(collect12.get(organId))).
					add(getAmount(collect20.get(organId))).add(getAmount(collect21.get(organId))).add(getAmount(collect23.get(organId))));
			operatingReportNew.setSalePrepaidFee(getAmount(collect13.get(organId)));
			operatingReportNew.setOtherPrepaidFee(getAmount(collect14.get(organId)));
			operatingReportNew.setPrepaidFee(operatingReportNew.getCloudPrepaidFee().
					add(operatingReportNew.getSalePrepaidFee()).
					add(operatingReportNew.getOtherPrepaidFee()).
					add(operatingReportNew.getCoursePrepaidFee()));

			operatingReportNew.setReceivables(getAmount(collect15.get(organId)).add(getAmount(collect16.get(organId))));
			operatingReportNew.setPayable(getAmount(collect17.get(organId)));

			operatingReportNew.setPrepayments(getAmount(collect19.get(organId)));

			operatingReportNew.setQuasiDiscretionaryProfit(operatingReportNew.getTotalIncome().subtract(operatingReportNew.getTotalCost()));
		}
		operatingReportNewDao.batchInsert(operatingList);
	}
	private BigDecimal getAmount(BigDecimal amount){
		if(amount == null){
			amount = BigDecimal.ZERO;
		}
		return amount;
	}
}