package com.dayou.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.dayou.bo.BrokerageDetailBO;
import com.dayou.bo.LeaderRatioBO;
import com.dayou.brokerage.BrokerageCalculateSupport;
import com.dayou.brokerage.BrokerageCalculator;
import com.dayou.brokerage.MarketerBrokerageCalculator;
import com.dayou.brokerage.NonMarketerMarketerBrokerageCalculator;
import com.dayou.brokerage.constants.BrokerageMode;
import com.dayou.brokerage.constants.BrokerageRule;
import com.dayou.brokerage.constants.BrokerageState;
import com.dayou.brokerage.validator.BrokerageValidator;
import com.dayou.common.BaseEntity;
import com.dayou.dto.ItemBrokerageGeneralDTO;
import com.dayou.dto.ItemDTO;
import com.dayou.dto.ParticipantSettleDTO;
import com.dayou.dto.SimplePostModel;
import com.dayou.entity.*;
import com.dayou.exception.ErrorCode;
import com.dayou.mapper.*;
import com.dayou.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dayou.utils.DateUtils;
import com.dayou.vo.BrokerageGeneralVO;
import com.dayou.vo.IdNameVO;
import com.dayou.vo.ItemStageVO;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.transaction.annotation.Transactional;

import static com.dayou.brokerage.constants.BrokerageRule.LAND_MARKETER_RULE;
import static com.dayou.common.Constants.*;

/**
 * <p>
 * 项目提成总表 服务实现类
 * </p>
 *
 * @author wucl
 * @since 2023-03-03
 */
@Slf4j
@Service
public class ItemBrokerageGeneralServiceImpl extends ServiceImpl<ItemBrokerageGeneralMapper, ItemBrokerageGeneral> implements IItemBrokerageGeneralService {


    @Autowired
    private BrokerageCalculateSupport brokerageCalculateSupport;

    @Autowired
    private IUserTargetService userTargetService;

    @Autowired
    private IItemBrokerageDetailService iItemBrokerageDetailService;

    @Autowired
    private IMarketStatService marketStatService;

    @Autowired
    private IUserPostService userPostService;

    @Autowired
    private ItemMapper itemMapper;

    @Autowired
    private ItemStageMapper itemStageMapper;

    @Autowired
    private ItemEvaluateMapper itemEvaluateMapper;

    @Autowired
    private PaymentCollectionMapper paymentCollectionMapper;

    @Autowired
    private ItemBrokerageGeneralMapper brokerageGeneralMapper;

    @Autowired
    private ITeamMemberService teamMemberService;

    @Autowired
    private MarketerBrokerageCalculator landMarketerBrokerageHandler;

    @Autowired
    private ItemBrokerageDetailMapper itemBrokerageDetailMapper;

    @Autowired
    private IUserService userService;

    @Autowired
    private IItemBrokerageGeneralService itemBrokerageGeneralService;


    @Override
    @SuppressWarnings("unchecked")
    public Page<BrokerageGeneralVO> selectPage(Page page, BrokerageGeneralVO itemBrokerageGeneral){
        Page<BrokerageGeneralVO> xPage = brokerageGeneralMapper.aheadPage(page,itemBrokerageGeneral);
        return xPage;
    }


    @Override
    public ItemBrokerageGeneral detail(Long id){
        return this.getById(id);
    }

    @Override
    public Boolean add(ItemBrokerageGeneral itemBrokerageGeneral){
        return  this.save(itemBrokerageGeneral);
    }

    @Override
    public Boolean update(ItemBrokerageGeneral itemBrokerageGeneral){
        return  this.updateById(itemBrokerageGeneral);
    }

    @Override
    public Boolean delete(Long id){
        //逻辑删除
        return this.removeById(id);
    }

    @Transactional
    @Override
    public void doCreateBrokerageGeneralAndDetail(BrokerageDetailBO bo) {
        MarketerBrokerageCalculator calculator = (MarketerBrokerageCalculator) brokerageCalculateSupport.getCalculator(LAND_MARKETER_RULE);
            Long userId = bo.getUserId();
        UserTarget userTarget = userTargetService.getUserTarget(userId);
        BigDecimal currentYearPayment = marketStatService.currentYearPayment(userId);
        BigDecimal paymentTarget = new BigDecimal(userTarget.getPaymentTarget());
        bo.setCurrentPayment(currentYearPayment);
        bo.setPaymentTarget(paymentTarget);


        Set<LeaderRatioBO> leaderRatioBO = teamMemberService.getLeader(bo.getUserId(), MARKET_DEPARTMENT).stream().filter(x->x.getRatio()!=null).collect(Collectors.toSet());
        //创建下单人领导提成记录
        Set<ItemBrokerageDetail> brokerageLeaderDetailBOS = Sets.newHashSet();
        BigDecimal leaderPredictTotalAmount = BigDecimal.ZERO;
        //创建下单人（客户经理或营销主管个人提成部分）提成记录
        if (bo.getBrokerageRule().equals(LAND_MARKETER_RULE.getCode())){
            bo = calculator.predictPersonalAmount(bo);
            brokerageLeaderDetailBOS.addAll(calculator.predictTeamShareAmount(bo, leaderRatioBO));
            leaderPredictTotalAmount = brokerageLeaderDetailBOS.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        if (bo.getBrokerageRule().equals(BrokerageRule.LAND_SUPERVISOR_RULE.getCode())){
            bo = calculator.supervisorPersonalAmount(bo);
            brokerageLeaderDetailBOS.addAll(calculator.predictTeamShareAmount(bo, leaderRatioBO));
            leaderPredictTotalAmount = brokerageLeaderDetailBOS.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        if (bo.getBrokerageRule().equals(BrokerageRule.LAND_MANAGER_RULE.getCode())){
            bo = calculator.managerPersonalAmount(bo);
        }
        //构建提成总表对象
        ItemBrokerageGeneral general = ItemBrokerageGeneral.builder()
                .itemId(bo.getItemId())
                .marketerBrokerageAmount(bo.getPredictAmount().add(leaderPredictTotalAmount))
                .marketerAdvanceBrokerageAble(bo.getMarketerAdvanceBrokerageAble())
                .participantActualBrokerageAmount(BigDecimal.ZERO)
                .participantPredictBrokerageAmount(BigDecimal.ZERO)
                .brokeragePredictAmount(bo.getPredictAmount().add(leaderPredictTotalAmount))
                .brokerageActualAmount(BigDecimal.ZERO)
                .participantStatus(BrokerageState.NOT_START.getCode())
                .marketerStatus(bo.getMarketerStatus())
                .brokerageRate(bo.getRate()).build();
        this.save(general);
        brokerageLeaderDetailBOS.add(bo);
        brokerageLeaderDetailBOS.stream().forEach(x->{ x.setGeneralId(general.getId());});
        iItemBrokerageDetailService.saveBatch(brokerageLeaderDetailBOS);
    }

    @Override
    public void addMarketerBrokerage(Long id) {
        Item item = itemMapper.selectById(id);
        Long userId = item.getUserId();
        //判断下单人是否是市场部人员
        Set<Long> marketers = userService.usersByDepartment(MARKET_DEPARTMENT).stream().map(IdNameVO::getId).collect(Collectors.toSet());
        if (!marketers.contains(userId)){
            log.info("下单人非市场部人员，终止提成流程创建。");
            return;
        }
        //下单人id
        BrokerageDetailBO brokerageDetailBO = BrokerageDetailBO.builder()
                .amount(item.getAmount())
                .cate(item.getCate())
                .businessSource(item.getBusinessSource())
                .itemId(id)
                .build();
        SimplePostModel postModel = userPostService.getMarketPostList(userId);
        String brokerageRule = LAND_MARKETER_RULE.getCode();
        if (postModel !=null){
            if (postModel.getName().equals(SUPERVISOR)){
                brokerageRule = BrokerageRule.LAND_SUPERVISOR_RULE.getCode();
            }
            if (postModel.getName().equals(MARKET_MANAGER)){
                brokerageRule = BrokerageRule.LAND_MANAGER_RULE.getCode();
            }
        }
        brokerageDetailBO.setBrokerageRule(brokerageRule);
        if (item.getAmount()!=null){
            brokerageDetailBO.setAdvanceAmount(BigDecimal.ZERO);
            brokerageDetailBO.setPredictAmount(BigDecimal.ZERO);
            brokerageDetailBO.setActualAmount(BigDecimal.ZERO);
            brokerageDetailBO.setAheadAmount(BigDecimal.ZERO);
            brokerageDetailBO.setMarketerStatus(BrokerageState.NOT_PAYMENT.getCode());
            brokerageDetailBO.setUserId(item.getUserId());
            itemBrokerageGeneralService.doCreateBrokerageGeneralAndDetail(brokerageDetailBO);
        }else {
            log.info("未设置合同金额，创建提成总表和客户经理提成记录终止。itemId[{}]",id);
        }

    }

    @Transactional
    @Override
    public void editMarketerBrokerage(ItemDTO itemDTO) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemDTO.getId());
        ItemBrokerageDetail marketerDetail = iItemBrokerageDetailService.getOne(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getGeneralId, general.getId())
                .eq(BaseEntity::getDeleted, Boolean.FALSE).eq(ItemBrokerageDetail::getBrokerageMode,BrokerageMode.PERSONAL.getCode()).eq(ItemBrokerageDetail::getBrokerageRule, LAND_MARKETER_RULE.getCode()));
        if (general == null || marketerDetail == null){
            log.info("更新项目信息时发现未创建提成总表和明细表记录，更新提成信息逻辑终止。");
            return;
        }
        MarketerBrokerageCalculator calculator = (MarketerBrokerageCalculator) brokerageCalculateSupport.getCalculator(LAND_MARKETER_RULE);
        //更新客户经理的提成记录

        BrokerageDetailBO brokerageDetailBO = BrokerageDetailBO.builder().amount(itemDTO.getAmount()).cate(itemDTO.getCate()).businessSource(itemDTO.getBusinessSource()).itemId(itemDTO.getId()).build();
        brokerageDetailBO.setUserId(marketerDetail.getUserId());
        brokerageDetailBO.setId(marketerDetail.getId());
        brokerageDetailBO.setGeneralId(general.getId());
        brokerageDetailBO.setMarketerStatus(general.getMarketerStatus());
        brokerageDetailBO.setBrokerageRule(marketerDetail.getBrokerageRule());
        //创建下单人提成记录
        if (brokerageDetailBO.getBrokerageRule().equals(LAND_MARKETER_RULE.getCode())){
            UserTarget userTarget = userTargetService.getUserTarget(marketerDetail.getUserId());
            BigDecimal currentMonthPayment = marketStatService.currentMonthPayment(marketerDetail.getUserId());
            BigDecimal paymentTarget = new BigDecimal(userTarget.getPaymentTarget());
            brokerageDetailBO.setPaymentTarget(paymentTarget);
            brokerageDetailBO.setCurrentPayment(currentMonthPayment);
            brokerageDetailBO = calculator.predictPersonalAmount(brokerageDetailBO);
        }
        if (brokerageDetailBO.getBrokerageRule().equals(BrokerageRule.LAND_SUPERVISOR_RULE.getCode())){
            brokerageDetailBO = calculator.supervisorPersonalAmount(brokerageDetailBO);
        }
        if (brokerageDetailBO.getBrokerageRule().equals(BrokerageRule.LAND_MANAGER_RULE.getCode())){
            brokerageDetailBO = calculator.managerPersonalAmount(brokerageDetailBO);
        }
        iItemBrokerageDetailService.update(brokerageDetailBO);


        BigDecimal leaderPredictTotalAmount = BigDecimal.ZERO;
        if (!brokerageDetailBO.getBrokerageRule().equals(BrokerageRule.LAND_MANAGER_RULE.getCode())){
            //更新领导提成记录
            //Set<LeaderRatioBO> leaderRatioBO = teamMemberService.getLeader(marketerDetail.getUserId(), MARKET_DEPARTMENT).stream().filter(x->x.getRatio()!=null).collect(Collectors.toSet());
            //Set<ItemBrokerageDetail> itemBrokerageDetails = calculator.predictTeamShareAmount(brokerageDetailBO, leaderRatioBO);
            List<ItemBrokerageDetail> list = iItemBrokerageDetailService.list(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getGeneralId, general.getId()).eq(ItemBrokerageDetail::getBrokerageMode, BrokerageMode.TEAM_SHARE.getCode()));
            //iItemBrokerageDetailService.saveBatch(itemBrokerageDetails);
            List<ItemBrokerageDetail>  itemBrokerageDetails = calculator.updateTeamShareAmount(list,brokerageDetailBO);
            iItemBrokerageDetailService.saveOrUpdateBatch(itemBrokerageDetails);
            leaderPredictTotalAmount = itemBrokerageDetails.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        //更新总表
        general.setMarketerBrokerageAmount(brokerageDetailBO.getPredictAmount().add(leaderPredictTotalAmount));
        general.setMarketerAdvanceBrokerageAble(brokerageDetailBO.getMarketerAdvanceBrokerageAble());
        general.setBrokerageRate(brokerageDetailBO.getRate());
        general.setBrokeragePredictAmount(brokerageDetailBO.getPredictAmount().add(general.getParticipantPredictBrokerageAmount()).add(leaderPredictTotalAmount));
        this.update(general);
    }

    @Override
    public void changeManagerBrokerage(ItemDTO itemDTO) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemDTO.getId());
        if (general!=null){
            iItemBrokerageDetailService.update(new LambdaUpdateWrapper<ItemBrokerageDetail>()
                .eq(ItemBrokerageDetail::getGeneralId, general.getId())
                .eq(ItemBrokerageDetail::getBrokerageMode,BrokerageMode.PERSONAL.getCode())
                    .eq(ItemBrokerageDetail::getBrokerageRule, LAND_MARKETER_RULE.getCode())
                .set(ItemBrokerageDetail::getUserId,itemDTO.getUserId()));
        }
    }

    @Transactional
    @Override
    public void removeMarketerBrokerage(Long itemId) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemId);
        this.removeById(general.getId());
        iItemBrokerageDetailService.remove(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getGeneralId,general.getId()));
    }

    @Transactional
    @Override
    public void addParticipatorBrokerage(ItemStageVO itemStageVO,Long brokerageStageId) {
        Item item = itemMapper.selectById(itemStageVO.getItemId());
        if (item.getAmount()!=null){
            NonMarketerMarketerBrokerageCalculator calculator = (NonMarketerMarketerBrokerageCalculator) brokerageCalculateSupport.getCalculator(BrokerageRule.LAND_OTHER_RULE);
            ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemStageVO.getItemId());
            if (general!=null){
                Set<ItemStageVO.ParticipatorWeight> participators = itemStageVO.getParticipators();
                Set<ItemBrokerageDetail> participatorBrokerageDetails = participators.stream().filter(s->s.getWeight()!=null).map(x -> {
                    BrokerageDetailBO brokerageDetailBO = BrokerageDetailBO.builder().build();
                    brokerageDetailBO.setBrokerageRule(BrokerageRule.LAND_OTHER_RULE.getCode());
                    brokerageDetailBO.setBrokerageMode(BrokerageMode.PERSONAL.getCode());
                    brokerageDetailBO.setAdvanceAmount(BigDecimal.ZERO);
                    brokerageDetailBO.setPredictAmount(BigDecimal.ZERO);
                    brokerageDetailBO.setActualAmount(BigDecimal.ZERO);
                    brokerageDetailBO.setAmount(item.getAmount());
                    brokerageDetailBO.setUserId(x.getUserId());
                    brokerageDetailBO.setGeneralId(general.getId());
                    brokerageDetailBO.setBrokerageStageId(brokerageStageId);
                    brokerageDetailBO.setStageWeight(itemStageVO.getWeight());
                    brokerageDetailBO.setParticipantWeight(x.getWeight());
                    brokerageDetailBO.setParticipantStatus(general.getParticipantStatus());
                    ItemBrokerageDetail itemBrokerageDetail = calculator.predictAmount(brokerageDetailBO);
                    return itemBrokerageDetail;
                }).collect(Collectors.toSet());
                BigDecimal participatorPredictTotalAmount = participatorBrokerageDetails.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

                //创建参与人的项目提成详情
                iItemBrokerageDetailService.saveBatch(participatorBrokerageDetails);
                //更新项目提成总表信息
                general.setParticipantPredictBrokerageAmount(participatorPredictTotalAmount.add(general.getParticipantPredictBrokerageAmount()));
                general.setParticipantAdvanceStatus(Boolean.TRUE);
                general.setBrokeragePredictAmount(general.getMarketerBrokerageAmount().add(general.getParticipantPredictBrokerageAmount()));
                general.setParticipantActualBrokerageAmount(BigDecimal.ZERO);
                general.setParticipantStatus(BrokerageState.PREDICTING.getCode());
                this.updateById(general);
            }

        }else {
            log.info("未设置合同金额，创建参与人提成记录终止。itemId[{}]",item.getId());
        }


    }

    @Transactional
    @Override
    public void editParticipatorBrokerage(ItemStageVO itemStageVO) {
        //从总表中 删除阶段中的预计提成和实际提成金额 更新总表
        List<ItemBrokerageDetail> list = iItemBrokerageDetailService.list(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getBrokerageStageId, itemStageVO.getId()));
        BigDecimal predictAmounts = list.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal actualAmounts = list.stream().map(ItemBrokerageDetail::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemStageVO.getItemId());
        general.setParticipantPredictBrokerageAmount(general.getParticipantPredictBrokerageAmount().subtract(predictAmounts));
        general.setParticipantActualBrokerageAmount(general.getParticipantActualBrokerageAmount().subtract(actualAmounts));
        general.setBrokeragePredictAmount(general.getBrokeragePredictAmount().subtract(predictAmounts));
        iItemBrokerageDetailService.remove(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getBrokerageStageId,itemStageVO.getId()));
        this.updateById(general);
        //如果项目已经被评价 需重新评价
        itemEvaluateMapper.delete(new LambdaQueryWrapper<ItemEvaluate>().eq(ItemEvaluate::getItemId,itemStageVO.getItemId()));
        itemBrokerageGeneralService.addParticipatorBrokerage(itemStageVO,itemStageVO.getId());
    }

    @Transactional
    @Override
    public void removeParticipatorBrokerage(Long itemStageId) {
        List<ItemBrokerageDetail> list = iItemBrokerageDetailService.list(new LambdaQueryWrapper<ItemBrokerageDetail>()
                .eq(ItemBrokerageDetail::getBrokerageStageId, itemStageId));
        if (CollectionUtils.isEmpty(list)){
            return ;
        }
        Long generalId = list.get(0).getGeneralId();
        if (generalId == null){
            return ;
        }
        ItemBrokerageGeneral general = this.getById(generalId);
        brokerageCalculateSupport.checkItemBrokerageStatusOnParticipantPredict(general.getParticipantStatus());
        BigDecimal participatorPredictTotalAmount = list.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal actualAmounts = list.stream().map(ItemBrokerageDetail::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        general.setParticipantPredictBrokerageAmount(general.getParticipantPredictBrokerageAmount().subtract(participatorPredictTotalAmount));
        general.setParticipantActualBrokerageAmount(general.getParticipantActualBrokerageAmount().subtract(actualAmounts));
        general.setBrokeragePredictAmount(general.getBrokeragePredictAmount().subtract(participatorPredictTotalAmount));
        this.updateById(general);
        iItemBrokerageDetailService.remove(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getBrokerageStageId,itemStageId));
    }

    @Transactional
    @Override
    public void toSettleParticipatorBrokerage(Long itemId) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemId);
        List<ItemStage> stages = itemStageMapper.selectList(new LambdaQueryWrapper<ItemStage>().eq(ItemStage::getItemId, itemId));
        ItemEvaluate settle = itemEvaluateMapper.selectOne(new LambdaQueryWrapper<ItemEvaluate>().eq(ItemEvaluate::getItemId, itemId).eq(BaseEntity::getDeleted, Boolean.FALSE));
        if (general!=null && CollectionUtils.isNotEmpty(stages) && settle!=null && settle.getWeight()!=null){
            NonMarketerMarketerBrokerageCalculator calculator = (NonMarketerMarketerBrokerageCalculator) brokerageCalculateSupport.getCalculator(BrokerageRule.LAND_OTHER_RULE);
            ParticipantSettleDTO participantSettle = ParticipantSettleDTO.builder().generalId(general.getId()).stages(stages).brokerageState(general.getParticipantStatus()).weight(settle.getWeight()).build();
            List<ItemBrokerageDetail> itemBrokerageDetails = calculator.actualAmount(participantSettle);
            iItemBrokerageDetailService.updateBatchById(itemBrokerageDetails);
            //结算后更新总表参与人提成总金额
            BigDecimal participatorActualTotalAmount = itemBrokerageDetails.stream().map(ItemBrokerageDetail::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            general.setParticipantActualBrokerageAmount(participatorActualTotalAmount);
            general.setParticipantAdvanceStatus(Boolean.FALSE);
//            general.setBrokerageActualAmount(participatorActualTotalAmount.add(general.getBrokerageActualAmount()));
            general.setParticipantStatus(BrokerageState.NOT_SETTLE.getCode());
            this.updateById(general);
        }else {
            log.info(ErrorCode.BROKERAGE_SETTLE_FAILED.getErrorMsg()+"项目id:[{}]",itemId);
        }

    }

    @Transactional
    @Override
    public void toSettleMarketerBrokerage(PaymentCollection payment) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(payment.getItemId());
        if (general!=null){
            Item item = itemMapper.selectById(payment.getItemId());
            List<PaymentCollection> paymentList = paymentCollectionMapper.selectList(new LambdaQueryWrapper<PaymentCollection>()
                    .eq(PaymentCollection::getItemId, payment.getItemId()).eq(BaseEntity::getDeleted, Boolean.FALSE));
            BigDecimal payDone = BigDecimal.valueOf(paymentList.stream().mapToDouble(PaymentCollection::getAmount).sum());
            brokerageCalculateSupport.checkItemBrokerageStatusOnMarketerPredict(general.getMarketerStatus());

            //如果此笔回款满足当月回款目标，则需要将上月签订的合同的预提状态改为 可预提
            //获取此笔回款项目的客户经理本年回款总额
            Long userId = itemMapper.selectById(payment.getItemId()).getUserId();
            BigDecimal currentYearPaymentAmount = marketStatService.currentYearPayment(userId);
            BigDecimal userTarget = new BigDecimal(userTargetService.getUserTarget(userId).getPaymentTarget());

            checkReturnPayment(payment, item, userId, currentYearPaymentAmount, userTarget);

            if (brokerageCalculateSupport.checkMarketerPredictBrokerage(currentYearPaymentAmount, userTarget)){
                //则需要将上月签订的合同的预提状态改为 可预提
                List<ItemBrokerageGeneral> lastMonthItemsBrokerages = itemMapper.getLastMonthItems(DateUtils.getLastMonth23(LocalDate.now().getYear(), LocalDate.now().getMonthValue() - 1),userId,BrokerageState.NOT_PAYMENT.getCode());
                if (CollectionUtils.isNotEmpty(lastMonthItemsBrokerages)){
                    lastMonthItemsBrokerages.stream().forEach(
                            i->{i.setMarketerAdvanceBrokerageAble(Boolean.TRUE);
                                i.setMarketerStatus(BrokerageState.TO_PREDICTING.getCode());
                            });
                    this.updateBatchById(lastMonthItemsBrokerages);

                    //修改提成详情表中预提金额

                    List<Long> generalIds = lastMonthItemsBrokerages.stream().map(ItemBrokerageGeneral::getId).collect(Collectors.toList());
                    List<ItemBrokerageDetail> details = itemBrokerageDetailMapper.getDetailForMarketer(generalIds);
                    details.stream().forEach(x->{
                        x.setAheadAmount( landMarketerBrokerageHandler.aheadAmount(x.getPredictAmount()));
                    });
                    iItemBrokerageDetailService.updateBatchById(details);
                    log.info("更新了客户经理预提状态待预提");
                }

            }
            if (item.getAmount()!=null && item.getAmount().compareTo(payDone)==0){
                general.setMarketerStatus(BrokerageState.NOT_SETTLE.getCode());
                this.updateById(general);
            }else {
                log.info("还有未回款项，暂不执行客户经理提成结算。");
            }
        }
        else {
            log.info("项目提成总表为创建，终止此流程。itemId[{}]",payment.getItemId());
        }
    }

    /**
     * 回款目标变动后，需重新计算客户经理的预提状态，和营销主管，营销经理的预提金额
     * @param userId
     * @param currentYearPaymentAmount
     * @param userTarget
     */
    private void checkUserTarget(Long userId,BigDecimal currentYearPaymentAmount, BigDecimal userTarget){
        Set<ItemBrokerageGeneralDTO> lastMonthTeamBrokerages = getLeaderBrokerageDetailsByCustomerManagerId(userId);
        MarketerBrokerageCalculator calculator = (MarketerBrokerageCalculator) brokerageCalculateSupport.getCalculator(LAND_MARKETER_RULE);
        lastMonthTeamBrokerages.stream().forEach(oGeneral->{
            Set<LeaderRatioBO> xLeader = teamMemberService.getLeader(oGeneral.getUserId(), MARKET_DEPARTMENT);
            Set<LeaderRatioBO> leaderRatioBO = xLeader.stream().filter(y->y.getRatio()!=null).collect(Collectors.toSet());
            BrokerageDetailBO brokerageDetailBO = buildBrokerageDetailBO(oGeneral);
            //本人的项目需计算预提金额
            Set<ItemBrokerageDetail> itemBrokerageDetails = Sets.newHashSet();
            String postName = userPostService.getMarketPostList(userId).getName();
            //如果该比提成总表显示客户经理 已预提，则不需要再次计算个人提成。
            if (postName.equals(CUSTOMER_MANAGER) && (userId.equals(oGeneral.getUserId())) && !oGeneral.getMarketerAdvanceBrokerageDone()){
                brokerageDetailBO.setCurrentPayment(currentYearPaymentAmount);
                brokerageDetailBO.setPaymentTarget(userTarget);
                BrokerageDetailBO xBrokerageDetailBO = calculator.predictPersonalAmount(brokerageDetailBO);

                Long id = iItemBrokerageDetailService.getOne(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getGeneralId, oGeneral.getId())
                        .eq(ItemBrokerageDetail::getBrokerageMode, BrokerageMode.PERSONAL.getCode())
                        .eq(ItemBrokerageDetail::getBrokerageRule, LAND_MARKETER_RULE.getCode())).getId();
                xBrokerageDetailBO.setId(id);
                itemBrokerageDetails.add(xBrokerageDetailBO);
            }
            //如果这些单子中下单人是营销经理
            if (userPostService.getMarketPostList(oGeneral.getUserId()).getName().equals(MARKET_MANAGER)){
                ItemBrokerageDetail one = iItemBrokerageDetailService.getOne(new LambdaQueryWrapper<ItemBrokerageDetail>()
                        .eq(ItemBrokerageDetail::getGeneralId, oGeneral.getId()).eq(ItemBrokerageDetail::getBrokerageMode, BrokerageMode.PERSONAL.getCode()));
                brokerageDetailBO = calculator.managerPersonalAmount(brokerageDetailBO);
                brokerageDetailBO.setId(one.getId());
                iItemBrokerageDetailService.updateById(brokerageDetailBO);
            }else {
                //更新领导的预计提成
                List<ItemBrokerageDetail> list = iItemBrokerageDetailService.list(new LambdaQueryWrapper<ItemBrokerageDetail>()
                        .eq(ItemBrokerageDetail::getGeneralId, oGeneral.getId()).eq(ItemBrokerageDetail::getBrokerageMode, BrokerageMode.TEAM_SHARE.getCode()));
                List<ItemBrokerageDetail> itemBrokerageDetails1 = calculator.updateTeamShareAmount(list, brokerageDetailBO);
                //Set<ItemBrokerageDetail> itemBrokerageLeaderDetails = calculator.predictTeamShareAmount(brokerageDetailBO, leaderRatioBO);
                itemBrokerageDetails.addAll(itemBrokerageDetails1);
                iItemBrokerageDetailService.saveOrUpdateBatch(itemBrokerageDetails);
            }
            BigDecimal leaderPredictTotalAmount = itemBrokerageDetails.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            oGeneral.setMarketerBrokerageAmount(brokerageDetailBO.getPredictAmount().add(leaderPredictTotalAmount));
            oGeneral.setMarketerAdvanceBrokerageAble(brokerageDetailBO.getMarketerAdvanceBrokerageAble());
            oGeneral.setBrokerageRate(brokerageDetailBO.getRate());
            oGeneral.setBrokeragePredictAmount(brokerageDetailBO.getPredictAmount().add(oGeneral.getParticipantPredictBrokerageAmount()).add(leaderPredictTotalAmount));
            ItemBrokerageGeneral original = ItemBrokerageGeneral.builder().build();
            BeanUtil.copyProperties(oGeneral,original);
            this.update(original);
        });
    }

    /**
     * 回款金额变动，需校验客户经理，营销主管，营销经理的回款目标是否达成，若达成需修改其他合同的预估提成金额
     * @param payment
     * @param item
     * @param userId
     * @param currentYearPaymentAmount
     * @param userTarget
     */
    private void checkReturnPayment(PaymentCollection payment, Item item, Long userId, BigDecimal currentYearPaymentAmount, BigDecimal userTarget) {

        Set<ItemBrokerageGeneralDTO> lastMonthTeamBrokerages = getLeaderBrokerageDetailsByCustomerManagerId(userId);
        MarketerBrokerageCalculator calculator = (MarketerBrokerageCalculator) brokerageCalculateSupport.getCalculator(LAND_MARKETER_RULE);
        lastMonthTeamBrokerages.stream().forEach(oGeneral->{
            //Set<LeaderRatioBO> xLeader = teamMemberService.getLeader(oGeneral.getUserId(), MARKET_DEPARTMENT);
            //Set<LeaderRatioBO> leaderRatioBO = xLeader.stream().filter(y->y.getRatio()!=null).collect(Collectors.toSet());
            BrokerageDetailBO brokerageDetailBO = buildBrokerageDetailBO(oGeneral);
            //本人的其他项目需计算预提金额
            Set<ItemBrokerageDetail> itemBrokerageDetails = Sets.newHashSet();
            String postName = userPostService.getMarketPostList(item.getUserId()).getName();
            if (postName.equals(CUSTOMER_MANAGER) && !oGeneral.getMarketerAdvanceBrokerageDone() && ( oGeneral.getItemId().equals(payment.getItemId()) || item.getUserId().equals(oGeneral.getUserId()))){
                brokerageDetailBO.setCurrentPayment(currentYearPaymentAmount);
                brokerageDetailBO.setPaymentTarget(userTarget);
                BrokerageDetailBO xBrokerageDetailBO = calculator.predictPersonalAmount(brokerageDetailBO);

                Long id = iItemBrokerageDetailService.getOne(new LambdaQueryWrapper<ItemBrokerageDetail>().eq(ItemBrokerageDetail::getGeneralId, oGeneral.getId())
                        .eq(ItemBrokerageDetail::getBrokerageMode, BrokerageMode.PERSONAL.getCode())
                        .eq(ItemBrokerageDetail::getBrokerageRule, LAND_MARKETER_RULE.getCode())).getId();
                xBrokerageDetailBO.setId(id);
                itemBrokerageDetails.add(xBrokerageDetailBO);
            }
            //如果这些单子中下单人是营销经理
            if (userPostService.getMarketPostList(oGeneral.getUserId()).getName().equals(MARKET_MANAGER)){
                ItemBrokerageDetail one = iItemBrokerageDetailService.getOne(new LambdaQueryWrapper<ItemBrokerageDetail>()
                        .eq(ItemBrokerageDetail::getGeneralId, oGeneral.getId()).eq(ItemBrokerageDetail::getBrokerageMode, BrokerageMode.PERSONAL.getCode()));
                brokerageDetailBO = calculator.managerPersonalAmount(brokerageDetailBO);
                brokerageDetailBO.setId(one.getId());
                iItemBrokerageDetailService.updateById(brokerageDetailBO);
            }else {
                //更新领导的预计提成
                List<ItemBrokerageDetail> list = iItemBrokerageDetailService.list(new LambdaQueryWrapper<ItemBrokerageDetail>()
                        .eq(ItemBrokerageDetail::getGeneralId, oGeneral.getId()).eq(ItemBrokerageDetail::getBrokerageMode, BrokerageMode.TEAM_SHARE.getCode()));
                List<ItemBrokerageDetail> itemBrokerageDetails1 = calculator.updateTeamShareAmount(list, brokerageDetailBO);
                //Set<ItemBrokerageDetail> itemBrokerageLeaderDetails = calculator.predictTeamShareAmount(brokerageDetailBO, leaderRatioBO);
                itemBrokerageDetails.addAll(itemBrokerageDetails1);
                iItemBrokerageDetailService.saveOrUpdateBatch(itemBrokerageDetails);
            }

            BigDecimal leaderPredictTotalAmount = itemBrokerageDetails.stream().map(ItemBrokerageDetail::getPredictAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            oGeneral.setMarketerBrokerageAmount(leaderPredictTotalAmount);
            oGeneral.setMarketerAdvanceBrokerageAble(brokerageDetailBO.getMarketerAdvanceBrokerageAble());
            oGeneral.setBrokerageRate(brokerageDetailBO.getRate());
            oGeneral.setBrokeragePredictAmount(oGeneral.getParticipantPredictBrokerageAmount().add(leaderPredictTotalAmount));
            ItemBrokerageGeneral original = ItemBrokerageGeneral.builder().build();
            BeanUtil.copyProperties(oGeneral,original);
            this.update(original);
        });
    }
    /**
     * 根据客户经理或营销主管的id获取其上级领导在上个月所生成的提成详情记录
     * @param userId 客户经理或营销主管的id
     * @return
     */
    private Set<ItemBrokerageGeneralDTO> getLeaderBrokerageDetailsByCustomerManagerId(Long userId) {
        //当某个客户经理达成当月回款目标后，需校验团队和部门是否达到当月回款目标。若达到则需重新就算 营销主管和营销经理的项目预计提成金额
        Set<LeaderRatioBO> leader = teamMemberService.getLeader(userId, MARKET_DEPARTMENT);
        Set<ItemBrokerageGeneralDTO> lastMonthTeamBrokerages = Sets.newHashSet();
        //找到当前回款订单的客户经理的领导，然后获取领导们的上月可提成的项目，由于营销主管和营销经理的项目存在重复，所以这里做了并集处理
        leader.stream().forEach(x->{
            //获取团队或部门上月签单的提成记录
            Set<Long> juniorUserIds = teamMemberService.getJuniorUserIds(x.getUserId());
            // 需要加上营销经理的userId,因为营销经理也可能下单
            juniorUserIds.add(x.getUserId());
            Set<ItemBrokerageGeneralDTO> xItemBrokerageGeneral = itemMapper.getLastMonthTeamItems(DateUtils.getLastMonth23(LocalDate.now().getYear(),
                    LocalDate.now().getMonthValue() - 1),juniorUserIds);
            lastMonthTeamBrokerages.addAll(xItemBrokerageGeneral);
        });
        return lastMonthTeamBrokerages;
    }



    private BrokerageDetailBO buildBrokerageDetailBO(ItemBrokerageGeneralDTO oGeneral) {
        BrokerageDetailBO bo = BrokerageDetailBO.builder().amount(oGeneral.getAmount()).marketerStatus(BrokerageState.NOT_PAYMENT.getCode()).build();
        bo.setGeneralId(oGeneral.getId());
        bo.setUserId(oGeneral.getUserId());
        bo.setBrokerageRule(LAND_MARKETER_RULE.getCode());
        bo.setMarketerStatus(BrokerageState.NOT_PAYMENT.getCode());
        bo.setRate(oGeneral.getBrokerageRate());
        bo.setAdvanceAmount(BigDecimal.ZERO);
        bo.setPredictAmount(BigDecimal.ZERO);
        bo.setActualAmount(BigDecimal.ZERO);
        bo.setAheadAmount(BigDecimal.ZERO);
        //客户经理预提金额
        bo.setPredictAmount(oGeneral.getAmount().multiply(oGeneral.getBrokerageRate()).divide(HUNDRED));
        return bo;
    }

    /**
     * 获取计算提成的项目 (待预提，待结算)
     * @return
     */
    @Override
    public List<ItemBrokerageGeneral> computedAbleList() {
        HashSet<String> status = Sets.newHashSet();
        status.add(BrokerageState.TO_PREDICTING.getCode());
        status.add(BrokerageState.NOT_SETTLE.getCode());
        status.add(BrokerageState.NOT_PAYMENT.getCode());
        status.add(BrokerageState.PREDICTED.getCode());
        List<ItemBrokerageGeneral> ableSettleList = this.list(new LambdaQueryWrapper<ItemBrokerageGeneral>().in(ItemBrokerageGeneral::getMarketerStatus,status)
                .or().eq(ItemBrokerageGeneral::getParticipantStatus,BrokerageState.NOT_SETTLE.getCode()));
        return ableSettleList;
    }

    @Override
    public Boolean updateMarketerStatus(Long id, Boolean marketerStatus) {
        boolean update = this.update(new LambdaUpdateWrapper<ItemBrokerageGeneral>().eq(BaseEntity::getId, id).set(ItemBrokerageGeneral::getMarketerAdvanceBrokerageAble, marketerStatus));
        return update;
    }

    @Override
    public void beforeToSettleParticipatorBrokerage(Long itemId) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemId);
        if (general!=null && general.getParticipantStatus().equals(BrokerageState.CLOSED.getCode())){
            ErrorCode.throwBusinessException(ErrorCode.BROKERAGE_ITEM_STATE_ERROR1);
        }
    }

    @Override
    public void beforeToSettleMarketerBrokerage(PaymentCollection payment) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(payment.getItemId());
        if (general!=null && general.getMarketerStatus().equals(BrokerageState.CLOSED.getCode())){
            ErrorCode.throwBusinessException(ErrorCode.BROKERAGE_ITEM_STATE_ERROR1);
        }
    }

    @Override
    public void beforeEditMarketerBrokerage(ItemDTO itemDTO) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemDTO.getId());
        if (general == null){
            addMarketerBrokerage(itemDTO.getId());
            log.info("更新项目信息时创建了相关的提成记录");
            return;
        }
        if (general.getMarketerStatus().equals(BrokerageState.CLOSED.getCode())){
            ErrorCode.throwBusinessException(ErrorCode.BROKERAGE_ITEM_STATE_ERROR1);
        }
    }

    @Override
    public void beforeAddParticipatorBrokerage(ItemStageVO itemStageVO) {
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemStageVO.getItemId());
        if (general == null){
            addMarketerBrokerage(itemStageVO.getItemId());
            itemBrokerageGeneralService.addParticipatorBrokerage(itemStageVO,itemStageVO.getId());
            log.info("更新项目信息时创建了相关的提成记录");
            return;
        }
        if (general.getParticipantStatus().equals(BrokerageState.CLOSED.getCode())){
            ErrorCode.throwBusinessException(ErrorCode.BROKERAGE_ITEM_STATE_ERROR1);
        }
    }

    @Override
    public void beforeRemoveParticipatorBrokerage(Long itemStageId) {
        ItemStage itemStage = itemStageMapper.selectById(itemStageId);
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(itemStage.getItemId());
        if (general!=null && general.getParticipantStatus().equals(BrokerageState.CLOSED.getCode())){
            ErrorCode.throwBusinessException(ErrorCode.BROKERAGE_ITEM_STATE_ERROR1);
        }
    }

    @Override
    public void beforeToSettleMarketerBrokerage(Long paymentId) {
        PaymentCollection payment = paymentCollectionMapper.selectById(paymentId);
        beforeToSettleMarketerBrokerage(payment);
    }

    @Transactional
    @Override
    public void toSettleMarketerBrokerage(Long paymentId) {
        PaymentCollection payment = paymentCollectionMapper.getDeleted(paymentId);

        //如果此笔回款满足当月回款目标，则需要将上月签订的合同的预提状态改为 可预提
        //获取此笔回款项目的客户经理本年回款总额
        Long userId = itemMapper.selectById(payment.getItemId()).getUserId();
        BigDecimal currentYearPaymentAmount = marketStatService.currentYearPayment(userId);
        BigDecimal userTarget = new BigDecimal(userTargetService.getUserTarget(userId).getPaymentTarget());
        if (!brokerageCalculateSupport.checkMarketerPredictBrokerage(currentYearPaymentAmount, userTarget)){
            //则需要将上月签订的合同的预提状态改为 不可预提
            List<ItemBrokerageGeneral> lastMonthItemsBrokerages = itemMapper.getLastMonthItems(DateUtils.getLastMonth23(LocalDate.now().getYear(), LocalDate.now().getMonthValue() - 1),userId,BrokerageState.TO_PREDICTING.getCode());
            if (CollectionUtils.isNotEmpty(lastMonthItemsBrokerages)){
                lastMonthItemsBrokerages.stream().forEach(
                        i->{i.setMarketerAdvanceBrokerageAble(Boolean.FALSE);
                            i.setMarketerStatus(BrokerageState.NOT_PAYMENT.getCode());
                        });
                this.updateBatchById(lastMonthItemsBrokerages);
                log.info("更新了客户经理预提状态为回款中");
            }
        }
        ItemBrokerageGeneral general = brokerageGeneralMapper.getByItemId(payment.getItemId());
        if (general.getMarketerStatus().equals(BrokerageState.NOT_SETTLE.getCode())){
            general.setMarketerStatus(BrokerageState.NOT_PAYMENT.getCode());
            this.updateById(general);
        }
    }

    @Override
    public void updateAheadStatus(Long userId) {
        BigDecimal currentYearPaymentAmount = marketStatService.currentYearPayment(userId);
        BigDecimal userTarget = new BigDecimal(userTargetService.getUserTarget(userId).getPaymentTarget());

        checkUserTarget(userId,currentYearPaymentAmount,userTarget);

        List<ItemBrokerageGeneral> lastMonthItemsBrokerages = itemMapper.getLastMonthItemsInStatus(DateUtils.getLastMonth23(LocalDate.now().getYear(), LocalDate.now().getMonthValue() - 1),userId);
        if (brokerageCalculateSupport.checkMarketerPredictBrokerage(currentYearPaymentAmount, userTarget) && CollectionUtils.isNotEmpty(lastMonthItemsBrokerages)){
            lastMonthItemsBrokerages.stream().forEach(
                    i->{i.setMarketerAdvanceBrokerageAble(Boolean.TRUE);
                        i.setMarketerStatus(BrokerageState.TO_PREDICTING.getCode());
                    });
            this.updateBatchById(lastMonthItemsBrokerages);
        }
        if (!brokerageCalculateSupport.checkMarketerPredictBrokerage(currentYearPaymentAmount, userTarget) && CollectionUtils.isNotEmpty(lastMonthItemsBrokerages)){
            lastMonthItemsBrokerages.stream().forEach(
                    i->{i.setMarketerAdvanceBrokerageAble(Boolean.FALSE);
                        i.setMarketerStatus(BrokerageState.NOT_PAYMENT.getCode());
                    });
            this.updateBatchById(lastMonthItemsBrokerages);
        }
    }

    @Override
    public ItemDTO getItemByBrokerageGeneralId(Long generalId) {
        return itemMapper.getItemByBrokerageGeneralId(generalId);
    }

    @Override
    public List<BrokerageGeneralVO> xList(BrokerageGeneralVO brokerageGeneralVO) {
        List<BrokerageGeneralVO> list = brokerageGeneralMapper.xList(brokerageGeneralVO);
        return list;
    }

}
