package com.td.boss.game.complayerprofit.service;

import cn.hutool.core.convert.Convert;
import com.td.boss.common.service.*;
import com.td.boss.game.commallseed.pojo.ComMallSeed;
import com.td.boss.game.commallseed.vo.ComMallSeedVo;
import com.td.boss.game.complayerland.pojo.ComPlayerLand;
import com.td.boss.game.complayerland.service.ComPlayerLandService;
import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
import com.td.boss.game.complayerprofit.pojo.ComPlayerProfit;
import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
import com.td.boss.game.complayerprofit.repository.ComPlayerProfitRepository;
import com.td.boss.game.complayersattri.vo.ComPlayersLuckyLandLevelUpVo;
import com.td.boss.util.CopyUtil;
import com.td.boss.util.DoubleUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

@Service
@Transactional
public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfitVo, ComPlayerProfit, String> implements ComPlayerProfitService {

    @PersistenceContext
    private EntityManager em;
    @Autowired
    private ComPlayerProfitRepository comPlayerProfitRepository;

    @Autowired
    private ComPlayerProfitService comPlayerProfitService;

    @Autowired
    private ComPlayerLandService comPlayerLandService;

    @Override
    public List<ComPlayerProfit> findByUserIdAndPlantFlagAndLandId(String userId, String plantFlag, Integer landId) {
        return comPlayerProfitRepository.findByTargetIdAndPlantFlagAndLandId(userId, plantFlag, landId);
    }

    @Override
    public ComPlayerProfit findByUserIdAndPlantFlag(String userId, String plantFlag) {
        return comPlayerProfitRepository.findByUserIdAndPlantFlag(userId, plantFlag).orElse(null);
    }

    @Override
    public ComPlayerProfit findByUserIdAndOtherUserIdAndPlantFlag(String userId, String otherUserId, String plantFlag) {
        return comPlayerProfitRepository.findByUserIdAndTargetIdAndPlantFlag(userId, otherUserId, plantFlag).orElse(null);
    }


    @Override
    public ComPlayerProfit findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId, String targetId, Integer configLandId, String plantFlag) {
        return comPlayerProfitRepository.findByUserIdAndTargetIdAndLandIdAndPlantFlag(userId, targetId, configLandId, plantFlag).orElse(null);
    }

    @Override
    public ComPlayerProfit findByPlantFlagAndLossTypeAndDsasterId(String plantFlag, Integer lossType,long dsaterId) {
        return comPlayerProfitRepository.findByPlantFlagAndLossTypeAndDsasterId(plantFlag, lossType,dsaterId).orElse(null);
    }

    @Override
    public Double getStolenSumByOtherUserIdAndPlantFlagAndLossType(String otherUserId, String plantFlag,Integer lossType) {
        return comPlayerProfitRepository.getStolenSumByTargetIdAndPlantFlagAndLossType(otherUserId, plantFlag,lossType);
    }


    @Override
    public ComPlayerProfitVo addFirstDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit ,long _dsasterId) {

        //对应土地灾害损失
        ComPlayerProfit comPlayerProfit = new ComPlayerProfit();
        //最终减扣的利润
        Double _endReduceProfit = 0d;
        //计算一个偷取的收获量, 租赁倍数* 租赁日期下的产量
        Integer _otherAmount = 0;
        if (comPlayerLand.getLeaseDate().equals(1)) {
            _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
        } else if (comPlayerLand.getLeaseDate().equals(2)) {
            _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest2();
        } else if (comPlayerLand.getLeaseDate().equals(3)) {
            _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
        }
        //todo 拿出全部利润
        Double landLevelInCome = getLandLevelInCome(comPlayerLand, comMallSeedVo.getPriceSnb());
        Integer _profitInt = _otherAmount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
        Double _profit =  DoubleUtil.add(_profitInt.doubleValue(),landLevelInCome);
        //todo 计算减产，第一次灾难按利润的 50% 减产，两次就是减到 0 了。

        //必然发生的灾难，减产40%
        Double _firstRatio = 0.4d;
        Double _reduceProfit = DoubleUtil.mul(_profit, _firstRatio);
        // 100 - 80 = 20
        Double _residualProfit = DoubleUtil.sub(_profit, allLossProfit);
        //剩余利润减去当前需要减产的利润值
        Double _tempProfit = DoubleUtil.sub(_residualProfit, _reduceProfit);
        if (!DoubleUtil.compare(_tempProfit, 0.0).equals(-1)) {
            //还有利润，
            _endReduceProfit = _reduceProfit;
        }

        comPlayerProfit.setUserId(comPlayerLand.getUserId()); //损失记录的用户id
        comPlayerProfit.setTargetId(comPlayerLand.getUserId()); //目标是自己
        comPlayerProfit.setPlantFlag(comPlayerLand.getPlantFlag());
        comPlayerProfit.setLandId(comPlayerLand.getConfigLandId());
        comPlayerProfit.setLeaseMultiple(comPlayerLand.getLeaseMultiple());
        comPlayerProfit.setLeaseDate(comPlayerLand.getLeaseDate());
        comPlayerProfit.setHarvest(_otherAmount); // todo
        comPlayerProfit.setProfit(_profit);//todo 目标用户可偷的初始利润值
        comPlayerProfit.setStolen(_endReduceProfit);//todo 目标用户被灾害减产对应的数量
        comPlayerProfit.setFinalSteal(_endReduceProfit);//
        comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(allLossProfit, _endReduceProfit))); //可偷的减去被偷的(包括灾难)

        //记录相关比例,损失利润的百分之40
        comPlayerProfit.setProfitRatio(_firstRatio);
        comPlayerProfit.setStealRatio(_firstRatio);
        comPlayerProfit.setFinalRatio(1.0);
        comPlayerProfit.setLossType(lossType);

        comPlayerProfit.setDsasterId(_dsasterId);
        comPlayerProfit.setAddedPart(landLevelInCome);

        ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
        comPlayerProfitService.save(comPlayerProfitVo);

        return comPlayerProfitVo;
    }


    @Override
    public ComPlayerProfitVo addOtherDisasterAndLoss(ComPlayerLand comPlayerLand, ComMallSeedVo comMallSeedVo, Integer lossType, Double allLossProfit, Integer disasterCount,long _dsasterId) {

        //对应土地灾害损失
        ComPlayerProfit comPlayerProfit = new ComPlayerProfit();
        //最终减扣的利润
        Double _endReduceProfit = 0d;
        //计算一个偷取的收获量, 租赁倍数* 租赁日期下的产量
        Integer _otherAmount = 0;
        if (comPlayerLand.getLeaseDate().equals(1)) {
            _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
        } else if (comPlayerLand.getLeaseDate().equals(2)) {
            _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest2();
        } else if (comPlayerLand.getLeaseDate().equals(3)) {
            _otherAmount = comPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
        }
        //todo 拿出全部利润
        Double landLevelInCome = getLandLevelInCome(comPlayerLand, comMallSeedVo.getPriceSnb());
        Integer _profitInt = _otherAmount - comPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
        Double _profit =  DoubleUtil.add(_profitInt.doubleValue(),landLevelInCome);
        //todo 计算减产，第一次灾难按利润的 100 减产 50，两次就是 50 减到 25。

        //额外发生的灾难，按照次数计算减产 50% 发生已经发生1次计算后当次等于 25%，
        double _startRatio = 0.5;
        for(int i = disasterCount;i>0;i--){
            _startRatio =  DoubleUtil.mul(_startRatio,0.5);
        }
        Double _reduceProfit = DoubleUtil.mul(_profit, _startRatio);
        // 100 - 80 = 20
        Double _residualProfit = DoubleUtil.sub(_profit, allLossProfit);
        //判断当前是否还存在可减去的利润
        if(DoubleUtil.compare(_residualProfit,0.0).equals(1)){
            //存在
            //剩余利润减去当前需要减产的利润值
            Double _tempProfit = DoubleUtil.sub(_residualProfit, _reduceProfit);
            if (DoubleUtil.compare(_tempProfit, 0.0).equals(-1)) {
                //负数说明全部被扣完
                _endReduceProfit = _residualProfit;

                //更新一下土地状态为不可偷窃状态
                comPlayerLand.setPlantSteal(0);
                comPlayerLandService.save(CopyUtil.copy(comPlayerLand, ComPlayerLandVo.class));

            }else{
                _endReduceProfit = _reduceProfit;
            }
        }
        //else{
        //    //不存在则默认是0
        //}


        comPlayerProfit.setUserId(comPlayerLand.getUserId()); //损失记录的用户id
        comPlayerProfit.setTargetId(comPlayerLand.getUserId()); //目标是自己
        comPlayerProfit.setPlantFlag(comPlayerLand.getPlantFlag());
        comPlayerProfit.setLandId(comPlayerLand.getConfigLandId());
        comPlayerProfit.setLeaseMultiple(comPlayerLand.getLeaseMultiple());
        comPlayerProfit.setLeaseDate(comPlayerLand.getLeaseDate());
        comPlayerProfit.setHarvest(_otherAmount); // todo
        comPlayerProfit.setProfit(_profit);//todo 目标用户可偷的初始利润值
        comPlayerProfit.setStolen(_endReduceProfit);//todo 目标用户被灾害减产对应的数量
        comPlayerProfit.setFinalSteal(_endReduceProfit);//
        comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(allLossProfit, _endReduceProfit))); //可偷的减去被偷的(包括灾难)

        //记录相关比例,损失利润的 _startRatio 相关比例
        comPlayerProfit.setProfitRatio(_startRatio);
        comPlayerProfit.setStealRatio(_startRatio);
        comPlayerProfit.setFinalRatio(1.0);
        comPlayerProfit.setLossType(lossType);

        comPlayerProfit.setDsasterId(_dsasterId);
        comPlayerProfit.setAddedPart(landLevelInCome);

        ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
        comPlayerProfitService.save(comPlayerProfitVo);

        return comPlayerProfitVo;
    }
    @Autowired
    private ComConfigService comConfigService;

    /**
     * 获得土地级别收益，普通土地最后结果为0
     * @param comPlayerLand
     * @param priceSnb
     * @return
     */
    private Double getLandLevelInCome( ComPlayerLand comPlayerLand, Integer priceSnb) {
        List<ComPlayersLuckyLandLevelUpVo> comPlayersLuckyLandLevelUpVos = comConfigService.selectLandLevel();
        ComPlayersLuckyLandLevelUpVo first = comPlayersLuckyLandLevelUpVos.stream()
                .filter(a -> a.getId().equals(comPlayerLand.getLandLevel()))
                .findFirst().orElse(null);
        //土地级别不存在
        if (first == null) {
            first = new ComPlayersLuckyLandLevelUpVo();
            first.setProduct(0);
        }
        Integer all = comPlayerLand.getLeaseMultiple() * priceSnb;
        return Convert.toDouble(all * first.getProduct() * 0.01);
    }
}
