package com.sifang.modules.sunshine.settleSet.service;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.account.dao.TraderAccountDao;
import com.sifang.modules.account.dao.TraderAccountSettleDetailDao;
import com.sifang.modules.account.entity.CrmTraderAccount;
import com.sifang.modules.customer.dao.CustomerEntryDao;
import com.sifang.modules.sunshine.SystemSetting.utils.StringUtil;
import com.sifang.modules.sunshine.settleSet.dao.RewardsPunishWayDao;
import com.sifang.modules.sunshine.settleSet.entity.CrmRewardsPunishWay;
import com.sifang.modules.sunshine.settleSet.vo.JobSaveLogVo;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.common.utils.IdGen;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service
public class CreateRewardsPunishSettleService extends BaseService {

    Logger logger= LoggerFactory.getLogger(getClass());

    @Autowired
    private RewardsPunishWayDao rewardsPunishWayDao;

    @Autowired
    private TraderAccountSettleDetailDao settleDetailDao;

    @Autowired
    private TraderAccountDao accountDao;

    @Autowired
    private CustomerEntryDao customerEntryDao;

    /**
     * 2、根据生效中的方案在下个月的1号凌晨生成上个月正月的规模返利记录；
     *       （1）代理商首次到货签收时间月和次月合并为一个统计月；（例如3.4号首次发货，那么4.1计算的时候，不计算3月的，等到5.1的时候一起计算）
     *       （2）每个电站生成一条奖励结算记录；
     *        （3）生成时状态默认为待生效，不可请款；
     *        （4）电站投放审核通过后，该电站的奖励结算记录状态改成未请款。
     * 3、完成安装的判断标准：确认物料安装已完成的时间（安装验收页面的“物料安装完成”复选框选中保存的物料安装完成时间）在安装完成时间内。
     */
    @Transactional(rollbackFor = Exception.class)
    public List<JobSaveLogVo> rewardsPunishSettle(){
        logger.info(">>>rewardsPunishSettle  开始统计");
        //先判断非上上月首次发货的代理商
       String sql=" SELECT IFNULL(SUM(e.actual_capacity),0) AS totalActualCapacity ,e.trader_name AS traderName,e.distributor_id AS traderId FROM `crm_customer_entry` e " +
               "LEFT JOIN `crm_trader` t ON e.distributor_id=t.id  " +
               "WHERE PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(e.material_fix_finish_time,'%Y%m'))=1 " +
               "AND  PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(t.first_deliver_time,'%Y%m'))>2 " +
               "GROUP BY e.distributor_id ";
        List<Record> list= Db.find(sql);
        logger.info(">>>rewardsPunishSettle list.size:{}",list.size());
        List<JobSaveLogVo> logVos=new ArrayList<>(); //只为记录一个过程信息
        //获取统一的奖励政策
        Record tyReward= rewardsPunishWayDao.getRewardsWayTy();
        Date date=new Date();
        if(list!=null && list.size()>0){
            List<String> entryIds=new ArrayList<>(); //改变电站表里面的是否已经奖励结算 if_reward_settle 字段
            for(Record r:list){
                Record traderReward=rewardsPunishWayDao.getRewardsWayByTraderId(r.get("traderId"));
                if(traderReward==null){
                   traderReward=tyReward;
                }
                logger.info("非上上月首次发货的代理商 traderReward:{} ",traderReward.getStr("id"));
                BigDecimal lowData1=new BigDecimal(traderReward.getStr("low_data"));
                BigDecimal highData1=new BigDecimal(traderReward.getStr("high_data"));
                BigDecimal ratioDta1=new BigDecimal(traderReward.getStr("ratio_data"));
                BigDecimal maxHighData=new BigDecimal(traderReward.getStr("max_high_data"));
                BigDecimal maxHighRatio=new BigDecimal(traderReward.getStr("max_high_data_radio"));
                //根据代理商获取上个月在奖励时间内的电站容量(先获取总容量判断)
                String sqlTrader="SELECT IFNULL(SUM(e.actual_capacity),0) AS totalActualCapacity ,e.trader_name AS traderName,e.distributor_id AS traderId FROM `crm_customer_entry` e " +
                        "LEFT JOIN `crm_trader` t ON e.distributor_id=t.id " +
                        "WHERE PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(e.material_fix_finish_time,'%Y%m'))=1 " +
                        "AND  PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(t.first_deliver_time,'%Y%m'))>2 " +
                        "AND e.distributor_id=? AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')>=? AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')<=?  GROUP BY e.distributor_id ";
                Record re=Db.findFirst(sqlTrader,r.get("traderId"),traderReward.getStr("lowTime"),traderReward.getStr("highTime"));
                logger.info("rewardsPunishSettle1 {},{} traderId:{},totalActualCapacity:{}",traderReward.getStr("lowTime"),traderReward.getStr("highTime"),r.getStr("traderId"),r.getBigDecimal("totalActualCapacity"));
                CrmTraderAccount traderAccount = accountDao.findByTraderId(r.get("traderId"));
                BigDecimal totalAmount=BigDecimal.ZERO; //总的代理商奖励的金额
                //总的安装容量 单位MW  1000000
                BigDecimal totalActualCapacity=re.getBigDecimal("totalActualCapacity").divide(new BigDecimal(1000000), 2, BigDecimal.ROUND_FLOOR);//运算后不要四舍五入
                logger.info(">>>>>>>>rewardsPunishSettle totalActualCapacity1:{}",totalActualCapacity);
                BigDecimal resultRadio=BigDecimal.ZERO; //这个是最终电站计算的
                if(totalActualCapacity.compareTo(maxHighData)>=0){  //如果大于最大的,那么按最大的算
                    resultRadio=maxHighRatio;
                    logger.info(">>>>>>>>rewardsPunishSettle set1 resultRadio:{}",resultRadio);
                }else if(totalActualCapacity.compareTo(lowData1)>=0 && totalActualCapacity.compareTo(highData1)<0){  //在一个区间里面
                    resultRadio=ratioDta1;
                    logger.info(">>>>>>>>rewardsPunishSettle set2 resultRadio:{}",resultRadio);
                }
                //逐个计算电站的奖励金额
                if(resultRadio.compareTo(BigDecimal.ZERO)>0){
                    String entrySql="SELECT e.id as entryId,e.power_station_code, e.actual_capacity ,e.distributor_id AS traderId,e.trader_name FROM `crm_customer_entry` e " +
                            "WHERE PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(e.material_fix_finish_time,'%Y%m'))=1 " +
                            "AND e.distributor_id=?  AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')>=? " +
                            " AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')<=? AND e.if_reward_settle<>'1' ";
                    List<Record> entryS=Db.find(entrySql,r.get("traderId"),traderReward.getStr("lowTime"),traderReward.getStr("highTime"));
                    for(Record entryR:entryS){
                        BigDecimal amount=entryR.getBigDecimal("actual_capacity").multiply(resultRadio).setScale(2,BigDecimal.ROUND_DOWN);//运算后不要四舍五入
                        settleDetailDao.saveSettle(entryR.getStr("entryId"),entryR.getStr("power_station_code"),entryR.getStr("traderId"),r.getStr("traderName"),amount,date,traderReward.getStr("number"));
                        entryIds.add(entryR.getStr("entryId"));
                        totalAmount=totalAmount.add(amount);
                        JobSaveLogVo jobSaveLogVo=new JobSaveLogVo(r.getStr("traderId"),amount,entryR.getStr("entryId"),entryR.getBigDecimal("actual_capacity"),traderReward.getStr("number"));
                        logVos.add(jobSaveLogVo);
                    }
                }
                if(totalAmount.compareTo(BigDecimal.ZERO)>0){ //产生了奖励金额
                    traderAccount.setSettleAmount(traderAccount.getSettleAmount().add(totalAmount));
                    traderAccount.setSettleRewardsPunishAmount(traderAccount.getSettleRewardsPunishAmount().add(totalAmount));
                    accountDao.save(traderAccount);
                }
            }
            if(entryIds.size()>0){
                customerEntryDao.changeIfRewardSettle(entryIds);
            }
        }

        //判断上上月首次发货的代理商（统计的是2个月的）
        String sql2=" SELECT IFNULL(SUM(e.actual_capacity),0) AS totalActualCapacity ,e.trader_name AS traderName,e.distributor_id AS traderId FROM `crm_customer_entry` e " +
                "LEFT JOIN `crm_trader` t ON e.distributor_id=t.id  " +
                "WHERE PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(e.material_fix_finish_time,'%Y%m'))=2 " +
                "AND  PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(t.first_deliver_time,'%Y%m'))=2 " +
                "GROUP BY e.distributor_id ";
        List<Record> list2= Db.find(sql2);
        logger.info(">>>>>rewardsPunishSettle  判断上上月首次发货的代理商 list2.size:{} ",list2.size());
        if(list2!=null && list2.size()>0){
            List<String> entryIds=new ArrayList<>(); //改变电站表里面的是否已经奖励结算 if_reward_settle 字段
            for(Record r:list2){
                Record traderReward=rewardsPunishWayDao.getRewardsWayByTraderId(r.get("traderId"));
                if(traderReward==null){
                    traderReward=tyReward;
                }
                logger.info("上上月首次发货的代理商 traderRewardId:{} ",traderReward.getStr("id"));
                BigDecimal lowData1=new BigDecimal(traderReward.getStr("low_data"));
                BigDecimal highData1=new BigDecimal(traderReward.getStr("high_data"));
                BigDecimal ratioDta1=new BigDecimal(traderReward.getStr("ratio_data"));
                BigDecimal maxHighData=new BigDecimal(traderReward.getStr("max_high_data"));
                BigDecimal maxHighRatio=new BigDecimal(traderReward.getStr("max_high_data_radio"));
                //根据代理商获取（上个月+上上月）在奖励时间内的电站容量(先获取总容量判断)
                String sqlTrader="SELECT IFNULL(SUM(e.actual_capacity),0) AS totalActualCapacity ,e.trader_name AS traderName,e.distributor_id AS traderId FROM `crm_customer_entry` e " +
                        "LEFT JOIN `crm_trader` t ON e.distributor_id=t.id " +
                        "WHERE PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(e.material_fix_finish_time,'%Y%m'))=2 " +
                        "AND  PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(t.first_deliver_time,'%Y%m'))=2 " +
                        "AND e.distributor_id=? AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')>=? AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')<=? ";
                Record re=Db.findFirst(sqlTrader,r.get("traderId"),traderReward.getStr("lowTime"),traderReward.getStr("highTime"));
                logger.info("rewardsPunishSettle2 traderId:{},totalActualCapacity:{}",r.getStr("traderId"),r.getBigDecimal("totalActualCapacity"));
                CrmTraderAccount traderAccount = accountDao.findByTraderId(r.get("traderId"));
                BigDecimal totalAmount=BigDecimal.ZERO; //总的代理商奖励的金额
                //总的安装容量 单位MW  1000000
                BigDecimal totalActualCapacity=re.getBigDecimal("totalActualCapacity").divide(new BigDecimal(1000000), 2, BigDecimal.ROUND_FLOOR);//运算后不要四舍五入
                logger.info(">>>>>>>>rewardsPunishSettle totalActualCapacity2:{}",totalActualCapacity);
                BigDecimal resultRadio=BigDecimal.ZERO; //这个是最终电站计算的
                if(totalActualCapacity.compareTo(maxHighData)>=0){  //如果大于最大的,那么按最大的算
                    resultRadio=maxHighRatio;
                    logger.info(">>>>>>>>rewardsPunishSettle set11 resultRadio:{}",resultRadio);
                }else if(totalActualCapacity.compareTo(lowData1)>=0 && totalActualCapacity.compareTo(highData1)<0){  //在一个区间里面
                    resultRadio=ratioDta1;
                    logger.info(">>>>>>>>rewardsPunishSettle set22 resultRadio:{}",resultRadio);
                }
                //逐个计算电站的奖励金额
                if(resultRadio.compareTo(BigDecimal.ZERO)>0){
                    String entrySql="SELECT e.id as entryId,e.power_station_code, e.actual_capacity ,e.distributor_id AS traderId,e.trader_name FROM `crm_customer_entry` e " +
                            "WHERE PERIOD_DIFF(DATE_FORMAT( NOW( ),'%Y%m' ),DATE_FORMAT(e.material_fix_finish_time,'%Y%m'))=1 " +
                            "AND e.distributor_id=?  AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')>=? " +
                            " AND DATE_FORMAT(e.material_fix_finish_time,'%Y-%m-%d')<=? AND e.if_reward_settle<>'1' ";
                    List<Record> entryS=Db.find(entrySql,r.get("traderId"),traderReward.getStr("lowTime"),traderReward.getStr("highTime"));
                    for(Record entryR:entryS){
                        BigDecimal amount=entryR.getBigDecimal("actual_capacity").multiply(resultRadio).setScale(2,BigDecimal.ROUND_DOWN);//运算后不要四舍五入
                        settleDetailDao.saveSettle(entryR.getStr("entryId"),entryR.getStr("power_station_code"),entryR.getStr("traderId"),r.getStr("traderName"),amount,date,traderReward.getStr("number"));
                        entryIds.add(entryR.getStr("entryId"));
                        totalAmount=totalAmount.add(amount);
                        JobSaveLogVo jobSaveLogVo=new JobSaveLogVo(r.getStr("traderId"),amount,entryR.getStr("entryId"),entryR.getBigDecimal("actual_capacity"),traderReward.getStr("number"));
                        logVos.add(jobSaveLogVo);
                    }
                }
                if(totalAmount.compareTo(BigDecimal.ZERO)>0){ //产生了奖励金额
                    traderAccount.setSettleAmount(traderAccount.getSettleAmount().add(totalAmount));
                    traderAccount.setSettleRewardsPunishAmount(traderAccount.getSettleRewardsPunishAmount().add(totalAmount));
                    accountDao.save(traderAccount);
                }
            }
            if(entryIds.size()>0){
                customerEntryDao.changeIfRewardSettle(entryIds);
            }
        }
        return logVos;
    }

    //判断奖惩政策是否失效，修改状态
    public void ifRewardsPunishSettleInvalid(){
        //处理失效
        String sql="  SELECT id FROM `crm_rewards_punish_way` WHERE high_time<DATE_FORMAT(NOW( ),'%Y-%m-%d') AND status='1' ";
        List<String> list=Db.query(sql);
        logger.info("ifRewardsPunishSettleInvalid  sql:{},list.size:{}",sql,list.size());
        if(list.size()>0){
            Db.update(" UPDATE `crm_rewards_punish_way` SET status='2' WHERE id IN ("+ StringUtil.joinInSql(list) +") ");
        }
        //处理生效
        int i= Db.update(" UPDATE `crm_rewards_punish_way` SET status='1' WHERE status='0' AND  low_data<=DATE_FORMAT(NOW( ),'%Y-%m-%d') ");
        logger.info(">>>>>>>>>ifRewardsPunishSettleInvalid  今天生效的奖励方案：{}",i);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW,noRollbackFor = Exception.class)
    public void saveNoCaseException(String e){
        Db.update("INSERT INTO `crm_time_job_log` VALUES(?,NOW(),?,?,?,?) ", IdGen.uuid(),"","执行失败",e,"1");
    }

    public static void main(String[] arr){
        /*BigDecimal c = new BigDecimal("27").divide(new BigDecimal("19"), 2, BigDecimal.ROUND_FLOOR);*/
        BigDecimal c2 = new BigDecimal("18.8").multiply(new BigDecimal("0.12"));
        System.out.println(c2.setScale(2,BigDecimal.ROUND_DOWN)+"-----"+c2);
    }
}
