package com.game.business.task;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.game.business.domain.*;
import com.game.business.service.*;
import com.game.common.constant.CacheConstants;
import com.game.common.constant.finance.FinTranType1;
import com.game.common.constant.finance.FinTranType3;
import com.game.common.core.domain.HttpRet;
import com.game.common.core.redis.RedisCache;
import com.game.common.entity.KeyValue;
import com.game.common.utils.DateUtils;
import com.game.common.utils.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component("appUserCountTask")
@Log4j2
public class AppUserCountTask {

    @Autowired
    private IAppUsersChargeService appUsersChargeService;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private IAppUsersCashrecordService appUsersCashrecordService;

    @Autowired
    private IFinTranRecordService finTranRecordService;

    @Autowired
    private IAppUserLiveDividedRecordService appUserLiveDividedRecordService;

    @Autowired
    private IAppUserGameRecordCountService appUserGameRecordCountService;

    @Autowired
    private IAppGameBettingService appGameBettingService;

    @Autowired
    private IAppUserCountService appUserCountService;

    @Autowired
    private IAppUserGameCountService appUserGameCountService;

    @Autowired
    private IAppUserAgentService appUserAgentService;

    @Autowired
    private IAppUserCountDividendService appUserCountDividendService;

    @Autowired
    private RedisCache redisCache;


    /**
     * 统计用户前一天
     * */
    public void statistics(String dateTime){
        String redisKey = CacheConstants.USER_STATICS_COUNT.concat("statistics");
        if(!redisCache.redisTemplate.opsForValue().setIfAbsent(redisKey,1)){
            log.info("停止统计用户每日直播、游戏、佣金，已在其他机器执行");
            return;
        }
        log.info("开始统计用户每日直播、游戏、佣金");
        try {
            Date curDate = DateUtil.offsetDay(DateUtils.getNowDate(), -1);
            if (StringUtils.isNotBlank(dateTime)) {
                curDate = DateUtil.parse(dateTime, "yyyy-MM-dd");
            } else {
                //清除前一天游戏返佣缓存

                dateTime = DateUtils.parseDateToStr("yyyy-MM-dd", curDate);
            }
            AppUser queryUser = new AppUser();
            queryUser.setAgentFlag(1);
            List<AppUser> list = appUserService.selectAppUserList(queryUser);//查询所有代理用户
            List<AppUsersCharge> appUsersChargeList = appUsersChargeService.getChargeList(null, dateTime.concat(" 00:00:00"), dateTime.concat(" 23:59:59"));
            List<AppUsersCashrecord> appUsersCashrecords = appUsersCashrecordService.getUserCashList(null, dateTime.concat(" 00:00:00"), dateTime.concat(" 23:59:59"));
            List<FinTranRecord> finTranRecordList = finTranRecordService.getUserRecordList(null, dateTime.concat(" 00:00:00"), dateTime.concat(" 23:59:59"));
            List<AppUserLiveDividedRecord> liveDividedRecordList = appUserLiveDividedRecordService.selectByDate(null, dateTime.concat(" 00:00:00"), dateTime.concat(" 23:59:59"));
            List<AppUserGameRecordCount> gameRecordCountList = appUserGameRecordCountService.selectByDate(null, dateTime.concat(" 00:00:00"), dateTime.concat(" 23:59:59"),null,null);
            List<AppGameBetting> gameBettingList = appGameBettingService.selectListByDate(null, dateTime.concat(" 00:00:00"), dateTime.concat(" 23:59:59"),null,null);
            Date nowDate = new Date();
            if (null != list && list.size() > 0) {
                List<AppUserCount> appUserCountList = new ArrayList<>();
                String finalDateTime = dateTime;
                list.forEach(appUser -> {
                    AppUserCount appUserCount = new AppUserCount();
                    appUserCount.setUserId(appUser.getUserid());
                    appUserCount.setStrDate(finalDateTime);
                    appUserCount.setAgentUserId(appUser.getPid());
                    appUserCount.setUpdate(true);//全量更新
                    appUserCount.setCountTime(nowDate);
                    appUserCount.setGameCountTime(nowDate);
                    appUserCount.setUpdateTime(nowDate);
                    //充值总额
                    appUserCount.setRechargeAmount(appUsersChargeList.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getCoin().doubleValue()).sum());
                    //提现金额
                    appUserCount.setWithdrawalAmount(appUsersCashrecords.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getMoney().doubleValue()).sum());
                    //充值服务费/手续费
                    appUserCount.setRechargeCommission(appUsersChargeList.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getPlatformService()).sum());
                    //充值赠送余额
                    /*appUserCount.setRechargeGive(finTranRecordList.stream().filter(e -> {
                        return e.getUid().equals(appUser.getUserid()) &&
                                e.getTranType1().intValue() == FinTranType1.U_Income_Coin_Balance.getType() &&
                                e.getTranType3().intValue() == FinTranType3.CHARGE_IN_REWARD.getType();
                    }).mapToDouble(e->e.getCoinChange()).sum());      */
                    appUserCount.setRechargeGive(appUsersChargeList.stream().filter(e -> {
                        return e.getUid().equals(appUser.getUserid());
                    }).mapToDouble(e->null==e.getCoinGive()?0:e.getCoinGive().doubleValue()).sum());
                    //提现服务费/手续费
                    appUserCount.setWithdrawalCommission(appUsersCashrecords.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getService().doubleValue()).sum());
                    //直播消费金额
                    Map<String, KeyValue> type1Keys = Arrays.stream(FinTranType1.getKeyValues(1)).collect(Collectors.toMap(e -> e.a, Function.identity(), (k1, k2) -> k2)); //支出交易类型
                    Map<String, KeyValue> type3Keys = Arrays.stream(FinTranType3.getKeyValues(1)).collect(Collectors.toMap(e -> e.a, Function.identity(), (k1, k2) -> k2)); //支出交易类型
                    appUserCount.setLiveUseAmount(finTranRecordList.stream().filter(e -> {
                        return e.getUid().equals(appUser.getUserid()) &&
                                null != type1Keys.get(String.valueOf(e.getTranType1().intValue())) &&
                                null != type3Keys.get(String.valueOf(e.getTranType3().intValue()));
                    }).mapToDouble(e -> dealMoney(e.getCoinChange())).sum());
                    //直播佣金
                    appUserCount.setLiveCommission(liveDividedRecordList.stream().filter(e -> e.getUserId().equals(appUser.getUserid())).mapToDouble(e -> e.getMoney().doubleValue()).sum());
                    //游戏下注金额
                    appUserCount.setGameBetting(gameBettingList.stream().filter(e->e.getUserId().equals(appUser.getUserid())).mapToDouble(AppGameBetting::getBettingAmount).sum());
                    //游戏佣金
                    appUserCount.setGameCommission(gameRecordCountList.stream().filter(e -> e.getUserId().equals(appUser.getUserid())).mapToDouble(e -> e.getCommission()).sum());
                    //直播间下注佣金
                    appUserCount.setGameCommission(gameRecordCountList.stream().filter(e -> e.getUserId().equals(appUser.getUserid()) && 1 == e.getType().intValue()).mapToDouble(e -> e.getCommission()).sum());
                    //游戏输
                    appUserCount.setGameLoseAmount(gameBettingList.stream().filter(
                            e -> e.getUserId().equals(appUser.getUserid()) && e.getIsWinning().intValue() == 2
                    ).mapToDouble(e ->
                            e.getBettingAmount()
                    ).sum());
                    //游戏赢
                    appUserCount.setGameWinAmount(gameBettingList.stream().filter(
                            e -> e.getUserId().equals(appUser.getUserid()) && e.getIsWinning().intValue() == 1
                    ).mapToDouble(e ->
                            e.getBettingAmount() * e.getBettingMultiple()
                    ).sum());
                    //邀请奖励
                    appUserCount.setLiveInvite(finTranRecordList.stream().filter(e->
                            e.getUid().equals(appUser.getUserid()) &&
                                    FinTranType3.CHARGE_IN_INVITE.getType() == e.getTranType3().intValue()
                    ).mapToDouble(FinTranRecord::getCoinChange).sum());
                    //直播收益
                    List<Integer> profitTypeList = Arrays.asList(
                            FinTranType3.CONSUM_LIVE_ROOM_REWARD.getType()
                    );
                    appUserCount.setLiveProfit(finTranRecordList.stream().filter(e->
                            e.getUid().equals(appUser.getUserid()) &&
                                    profitTypeList.contains(e.getTranType3()) &&
                                    FinTranType1.U_Income_Coin.getType() == e.getTranType1().intValue()
                    ).mapToDouble(FinTranRecord::getCoinChange).sum());
                    appUserCountService.createAppUserCount(appUserCount);
                });
            }
            //统计游戏返佣缓存
            appUserCountService.setGameCache(gameRecordCountList);

            //统计当日用户游戏输赢
            if (null != gameBettingList && gameBettingList.size() > 0) {
                Map<String, List<AppGameBetting>> map = gameBettingList.stream().
                        collect(Collectors.groupingBy(
                                e -> String.valueOf(e.getUserId()).concat("_").
                                        concat(String.valueOf(e.getGameId())).
                                        concat("_").concat(String.valueOf(e.getIsWinning()))
                        ));
                for (String key : map.keySet()) {
                    List<AppGameBetting> appGameBettingList = map.get(key);
                    Long userId = Long.valueOf(key.split("_")[0]);
                    Long gameId = Long.valueOf(key.split("_")[1]);
                    AppUserGameCount appUserGameCount = new AppUserGameCount();
                    appUserGameCount.setUserId(userId);
                    appUserGameCount.setGameId(gameId);
                    appUserGameCount.setStrDate(dateTime);
                    appUserGameCount.setGameLoseAmount(appGameBettingList.stream().filter(e -> 2 == e.getIsWinning()).mapToDouble(
                            e -> e.getBettingAmount()
                    ).sum());
                    appUserGameCount.setGameWinAmount(appGameBettingList.stream().filter(e -> 2 == e.getIsWinning()).mapToDouble(
                            e -> e.getBettingAmount() * e.getBettingMultiple()
                    ).sum());
                    appUserGameCount.setGameCommission(gameRecordCountList.stream().filter(
                            e -> e.getUserId().equals(userId) && e.getGameId().equals(gameId)
                    ).mapToDouble(e -> e.getCommission()).sum());//自己得到的佣金
                    appUserGameCountService.save(appUserGameCount);
                }
            }
        }catch (Exception e){
            log.info("用户每日直播、游戏、佣金统计异常：{}",e.getMessage());
        } finally {
            redisCache.redisTemplate.delete(redisKey);
        }
        log.info("用户每日直播、游戏、佣金统计完成");

    }

    /**
     * 统计用户直播/充值 (增量更新 1分钟)
     * */
    public void statisticsLive(){
        String redisKey = CacheConstants.USER_STATICS_COUNT.concat("statisticsLive");
        if(!redisCache.redisTemplate.opsForValue().setIfAbsent(redisKey,1)){
            log.info("停止增量更新用户每日直播、佣金，已在其他机器执行");
            return;
        }
        log.info("开始增量更新用户每日直播、佣金");
        try {
            Long userId = null;
            Date curDate = new Date();
            String dateTime = DateUtil.format(curDate, "yyyy-MM-dd");
            Date lastDate = appUserCountService.selectLastDate();
            String lastDateStr = DateUtil.format(lastDate,"yyyy-MM-dd HH:mm:ss");
            if(!dateTime.equals(DateUtil.format(lastDate,"yyyy-MM-dd"))){
                lastDateStr = DateUtil.format(curDate, "yyyy-MM-dd").concat(" 00:00:00");
            }
            String endTimeStr = DateUtil.format(curDate,"yyyy-MM-dd HH:mm:ss");
            AppUser queryUser = new AppUser();
            queryUser.setAgentFlag(1);
            List<AppUser> list = appUserService.selectAppUserList(queryUser);//查询所有代理用户
            List<AppUsersCharge> appUsersChargeList = appUsersChargeService.getChargeList(userId, lastDateStr, endTimeStr);
            List<AppUsersCashrecord> appUsersCashrecords = appUsersCashrecordService.getUserCashList(userId, lastDateStr, endTimeStr);
            List<FinTranRecord> finTranRecordList = finTranRecordService.getUserRecordList(null!=userId?String.valueOf(userId):null, lastDateStr, endTimeStr);
            List<AppUserLiveDividedRecord> liveDividedRecordList = appUserLiveDividedRecordService.selectByDate(userId, lastDateStr, endTimeStr);
            if (null != list && list.size() > 0) {
//                List<AppUserCount> appUserCountList = new ArrayList<>();
                String finalDateTime = dateTime;
                list.forEach(appUser -> {
                    AppUserCount appUserCount = new AppUserCount();
                    appUserCount.setUserId(appUser.getUserid());
                    appUserCount.setStrDate(finalDateTime);
                    appUserCount.setAgentUserId(appUser.getPid());
                    appUserCount.setCountTime(curDate);
                    //充值总额
                    appUserCount.setRechargeAmount(appUsersChargeList.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getCoin().doubleValue()).sum());
                    //提现金额
                    appUserCount.setWithdrawalAmount(appUsersCashrecords.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getMoney().doubleValue()).sum());
                    //充值服务费/手续费
                    appUserCount.setRechargeCommission(appUsersChargeList.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getPlatformService()).sum());
                    //充值赠送余额
                    /*appUserCount.setRechargeGive(finTranRecordList.stream().filter(e -> {
                        return e.getUid().equals(appUser.getUserid()) &&
                                e.getTranType1().intValue() == FinTranType1.U_Income_Coin_Balance.getType() &&
                                e.getTranType3().intValue() == FinTranType3.CHARGE_IN_REWARD.getType();
                    }).mapToDouble(e->e.getCoinChange()).sum());*/
                    appUserCount.setRechargeGive(appUsersChargeList.stream().filter(e -> {
                        return e.getUid().equals(appUser.getUserid());
                    }).mapToDouble(e->null==e.getCoinGive()?0:e.getCoinGive().doubleValue()).sum());
                    //提现服务费/手续费
                    appUserCount.setWithdrawalCommission(appUsersCashrecords.stream().filter(e -> e.getUid().equals(appUser.getUserid())).mapToDouble(e -> e.getService().doubleValue()).sum());
                    //直播消费金额
                    Map<String, KeyValue> type1Keys = Arrays.stream(FinTranType1.getKeyValues(1)).collect(Collectors.toMap(e -> e.a, Function.identity(), (k1, k2) -> k2)); //支出交易类型
                    Map<String, KeyValue> type3Keys = Arrays.stream(FinTranType3.getKeyValues(1)).collect(Collectors.toMap(e -> e.a, Function.identity(), (k1, k2) -> k2)); //支出交易类型
                    appUserCount.setLiveUseAmount(finTranRecordList.stream().filter(e -> {
                        return e.getUid().equals(appUser.getUserid()) &&
                                null != type1Keys.get(String.valueOf(e.getTranType1().intValue())) &&
                                null != type3Keys.get(String.valueOf(e.getTranType3().intValue()));
                    }).mapToDouble(e -> dealMoney(e.getCoinChange())).sum());
                    //直播佣金
                    appUserCount.setLiveCommission(liveDividedRecordList.stream().filter(e -> e.getUserId().equals(appUser.getUserid())).mapToDouble(e -> e.getMoney().doubleValue()).sum());
                    //邀请奖励
                    appUserCount.setLiveInvite(finTranRecordList.stream().filter(e->
                            e.getUid().equals(appUser.getUserid()) &&
                            FinTranType3.CHARGE_IN_INVITE.getType() == e.getTranType3().intValue()
                    ).mapToDouble(FinTranRecord::getCoinChange).sum());
                    //直播收益
                    List<Integer> profitTypeList = Arrays.asList(
                            FinTranType3.CONSUM_LIVE_ROOM_REWARD.getType()
                    );
                    appUserCount.setLiveProfit(finTranRecordList.stream().filter(e->
                            e.getUid().equals(appUser.getUserid()) &&
                                    profitTypeList.contains(e.getTranType3()) &&
                                    FinTranType1.U_Income_Coin.getType() == e.getTranType1().intValue()
                    ).mapToDouble(FinTranRecord::getCoinChange).sum());
                    appUserCountService.createAppUserCount(appUserCount);
                });
            }
        }catch (Exception e){
            log.info("增量更新用户每日直播、佣金统计异常：{}",e.getMessage());
        } finally {
            redisCache.redisTemplate.delete(redisKey);
        }
        log.info("增量更新用户每日直播、佣金统计完成");

    }

    /**
     * 计算分红
     * @param dateTime 格式yyyy-MM-dd
     * */
    @DSTransactional
    public void calculateDividends(String dateTime){
        String redisKey = CacheConstants.USER_STATICS_COUNT.concat("calculateDividends");
        if(!redisCache.redisTemplate.opsForValue().setIfAbsent(redisKey,1)){
            log.info("停止每周代理分红，已在其他机器执行");
            return;
        }
        try {
            log.info("开始每周代理分红");
            String dateNo =  dealDividendsNew(dateTime);
            log.info("每周代理分红完成");
            log.info("开始给系统用户的直属下级自动发放分红");
            AppUser queryUser = new AppUser();
            queryUser.setPid(0L);
            List<AppUser> list = appUserService.selectAppUserList(queryUser);
            if(null != list && list.size() > 0){
                for(AppUser appUser : list){
                    HttpRet<Boolean> httpRet = appUserCountDividendService.send(null,dateNo,appUser.getUserid());
                    if(HttpRet.FAIL == httpRet.getCode()){
                        log.info("{}用户，{}",appUser.getUserid(),httpRet.getMsg());
                    }
                }
            }
            log.info("系统用户的直属下级自动发放分红完成");
        }catch (Exception e){
            log.info("每周分红失败：{}",e.getMessage());
        }finally {
            redisCache.redisTemplate.delete(redisKey);
        }

    }

    /**
     * 分红（已废弃）
     * */
    private void dealDividends(String dateTime){
        Date curDate = DateUtil.offsetDay(DateUtils.getNowDate(), -1);
        if (StringUtils.isNotBlank(dateTime)) {
            curDate = DateUtil.parse(dateTime, "yyyy-MM-dd");
        } else {
            dateTime = DateUtils.parseDateToStr("yyyy-MM-dd", curDate);
        }
        Date beginTime = DateUtil.beginOfWeek(curDate);
        Date endTime = DateUtil.endOfWeek(curDate);
        //查询所有总代理用户
        AppUser queryUser = new AppUser();
        queryUser.setAgentFlag(1);
        List<AppUser> list = appUserService.selectAppUserList(queryUser);
//            List<AppUser> list = appUserService.selectTeamUserList();
        if (null != list && list.size() > 0) {
            list.forEach(appUser -> {
                String beginTimeStr = DateUtil.format(beginTime,"yyyy-MM-dd");
                String endTimeStr = DateUtil.format(endTime,"yyyy-MM-dd");
                //查询用户所有下级本周盈亏
                    /*LambdaQueryWrapper<AppUserCount> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.ge(AppUserCount::getStrDate, beginTimeStr);
                    queryWrapper.le(AppUserCount::getStrDate, endTimeStr);
                    queryWrapper.eq(AppUserCount::getAgentUserId, appUser.getUserid());
                    List<AppUserCount> appUserCountList = appUserCountService.list(queryWrapper);*/
                List<AppUserCount> appUserCountList = appUserCountService.getAppUserCountNew(appUser.getUserid(),beginTimeStr,endTimeStr);
                if (null != appUserCountList && appUserCountList.size() > 0) {
                    //游戏输钱
                    double loseAmount = appUserCountList.stream().mapToDouble(e -> e.getGameLoseAmount()).sum();
                    //游戏赢钱
                    double winAmount = appUserCountList.stream().mapToDouble(e -> e.getGameWinAmount()).sum();
                    //提现手续费
                    double withdrawalCommission = appUserCountList.stream().mapToDouble(e -> e.getWithdrawalCommission()).sum();
                    //游戏佣金
                    double gameCommission = appUserCountList.stream().mapToDouble(e -> e.getGameCommission()).sum();
                    //直播佣金
                    double liveCommission = appUserCountList.stream().mapToDouble(e -> e.getLiveCommission()).sum();
                    //充值赠送
                    double rechargeGive = appUserCountList.stream().mapToDouble(e -> e.getRechargeGive()).sum();

                    //计算分红金额 （输-赢）
//                        double money = (loseAmount - winAmount) - withdrawalCommission - gameCommission - liveCommission;
                    double money = (loseAmount - winAmount)  - gameCommission - rechargeGive;
                    if (money > 0) {
                        //金额大于0 满足分红
                        //查询当前用户所有下级
                        AppUserAgent queryAppUserAgent = new AppUserAgent();
                        queryAppUserAgent.setPid(appUser.getUserid());
                        List<AppUserAgent> appUserAgentList = appUserAgentService.selectAppUserAgentList(queryAppUserAgent);
                        if (null != appUserAgentList && appUserAgentList.size() > 0) {
                            appUserAgentList.forEach(userAgent -> {
                                if (userAgent.getDividendGuaranteeRate() <= 0.00) {
                                    log.info("用户{}，团队亏损{}，或未设置分红比例，停止分红", userAgent.getUserId(), money);
                                    return;
                                }
                                double rate = userAgent.getDividendGuaranteeRate();
                                double dividends = BigDecimal.valueOf(money * rate/100).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
                                AppUserCountDividend appUserCountDividend = new AppUserCountDividend();
                                appUserCountDividend.setUserId(userAgent.getUserId());
                                appUserCountDividend.setDateNo(DateUtil.format(endTime, "yyyy-MM-dd"));
                                appUserCountDividend.setBeginTime(beginTime);
                                appUserCountDividend.setEndTime(endTime);
                                appUserCountDividend.setProfitLoss(money);
                                appUserCountDividend.setRate(rate);
                                appUserCountDividend.setCoin(0.00);
                                appUserCountDividend.setDiamondCoin(dividends);
                                appUserCountDividend.setStatus(0);
                                appUserCountDividendService.insertAppUserCountDividend(appUserCountDividend);
                            });
                        } else {
                            log.info("用户{}，所有下级亏损{}，查询下级为空，停止分红", appUser.getUserid(), money);
                        }
                    } else {
                        log.info("用户{}，所有下级亏损{}，不满足分红条件", appUser.getUserid(), money);
                    }
                }
            });
        }
    }

    /**
     * 分红
     * */
    private String dealDividendsNew(String dateTime){
        String resDate = "";
        Date curDate = DateUtil.offsetDay(DateUtils.getNowDate(), -1);
        if (StringUtils.isNotBlank(dateTime)) {
            curDate = DateUtil.parse(dateTime, "yyyy-MM-dd");
        } else {
            dateTime = DateUtils.parseDateToStr("yyyy-MM-dd", curDate);
        }
        Date beginTime = DateUtil.beginOfWeek(curDate);
        Date endTime = DateUtil.endOfWeek(curDate);

        Date weekBegin = null;
        Date weekend = null;
        int curDay = Integer.parseInt(DateUtil.format(curDate,"dd"));
        if(curDay <= 15){
            weekBegin = DateUtil.beginOfMonth(curDate);
            weekend = DateUtil.parse(DateUtil.format(curDate,"yyyy-MM-".concat("15").concat(" 23:59:59")),"yyyy-MM-dd HH:mm:ss");
        }else{
            weekBegin = DateUtil.parse(DateUtil.format(curDate,"yyyy-MM-".concat("15").concat(" 00:00:00")),"yyyy-MM-dd HH:mm:ss");
            weekend = DateUtil.endOfMonth(curDate);
        }

        resDate = DateUtil.format(endTime, "yyyy-MM-dd");
        //查询所有总代理用户
        AppUser queryUser = new AppUser();
        queryUser.setAgentFlag(1);
        List<AppUser> list = appUserService.selectAppUserList(queryUser);
//            List<AppUser> list = appUserService.selectTeamUserList();
        if (null != list && list.size() > 0) {
            list.forEach(appUser -> {
                AppUserAgent userAgent = appUserAgentService.selectInfo(appUser.getUserid());
                if (userAgent.getDividendGuaranteeRate() <= 0.00) {
                    log.info("用户{}，未设置分红比例，停止分红", userAgent.getUserId());
                    return;
                }
                String beginTimeStr = DateUtil.format(beginTime,"yyyy-MM-dd");
                String endTimeStr = DateUtil.format(endTime,"yyyy-MM-dd");
                //查询用户所有下级本周盈亏
                    /*LambdaQueryWrapper<AppUserCount> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.ge(AppUserCount::getStrDate, beginTimeStr);
                    queryWrapper.le(AppUserCount::getStrDate, endTimeStr);
                    queryWrapper.eq(AppUserCount::getAgentUserId, appUser.getUserid());
                    List<AppUserCount> appUserCountList = appUserCountService.list(queryWrapper);*/
                List<AppUserCount> appUserCountList = appUserCountService.getAppUserCountNew(appUser.getUserid(),beginTimeStr,endTimeStr);
                if (null != appUserCountList && appUserCountList.size() > 0) {
                    //游戏输钱
                    double loseAmount = appUserCountList.stream().mapToDouble(e -> e.getGameLoseAmount()).sum();
                    //游戏赢钱
                    double winAmount = appUserCountList.stream().mapToDouble(e -> {
                        return e.getGameWinAmount() - (e.getGameBetting() - e.getGameLoseAmount()); //实际赢钱 = 赢 - 中奖本金
                    }).sum();
                    //提现手续费
                    double withdrawalCommission = appUserCountList.stream().mapToDouble(e -> e.getWithdrawalCommission()).sum();
                    //充值手续费
                    double rechargeCommission = appUserCountList.stream().mapToDouble(e -> e.getRechargeCommission()).sum();
                    //游戏佣金
                    double gameCommission = appUserCountList.stream().mapToDouble(e -> e.getGameCommission()).sum();
                    //直播佣金
                    double liveCommission = appUserCountList.stream().mapToDouble(e -> e.getLiveCommission()).sum();
                    //充值赠送
                    double rechargeGive = appUserCountList.stream().mapToDouble(e -> e.getRechargeGive()).sum();

                    //计算分红金额 （输-赢）
//                        double money = (loseAmount - winAmount) - withdrawalCommission - gameCommission - liveCommission;
                    double money = (loseAmount - winAmount)  - gameCommission - rechargeGive - rechargeCommission - withdrawalCommission;
                    if (money > 0) {
                        //金额大于0 满足分红
                        double rate = userAgent.getDividendGuaranteeRate();
                        double dividends = BigDecimal.valueOf(money * rate/100).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
                        AppUserCountDividend appUserCountDividend = new AppUserCountDividend();
                        appUserCountDividend.setUserId(userAgent.getUserId());
                        appUserCountDividend.setDateNo(DateUtil.format(endTime, "yyyy-MM-dd"));
                        appUserCountDividend.setBeginTime(beginTime);
                        appUserCountDividend.setEndTime(endTime);
                        appUserCountDividend.setProfitLoss(money);
                        appUserCountDividend.setRate(rate);
                        appUserCountDividend.setCoin(0.00);
                        appUserCountDividend.setDiamondCoin(dividends);
                        appUserCountDividend.setStatus(0);
                        appUserCountDividendService.insertAppUserCountDividend(appUserCountDividend);
                    } else {
                        log.info("用户{}，所有下级亏损{}，没有亏损停止分红", appUser.getUserid(), money);
                    }
                } else {
                    log.info("用户{}，团队没有流水停止分红", appUser.getUserid());
                }
            });
        }
        return resDate;
    }

    /**
     * 更新用户下级列表
     * */
    public void statisticsTeam(){
        AppUserAgent query = new AppUserAgent();
        List<AppUserAgent> userAgents = appUserAgentService.selectAppUserAgentList(query);
        userAgents.forEach(appUserAgent -> {
            AppUserAgent updateAgent = new AppUserAgent();
            updateAgent.setId(appUserAgent.getId());
            List<String> userIds = userAgents.stream().filter(e->e.getPid().equals(appUserAgent.getUserId())).map(e->{return String.valueOf(e.getUserId());}).collect(Collectors.toList());
            updateAgent.setSubset(String.join(",",userIds));
            appUserAgentService.updateAppUserAgent(updateAgent);
        });
    }

    public void reloadDividendCache(String dateTime,String topUserId){
        appUserCountDividendService.reloadCache(dateTime,StringUtils.isBlank(topUserId)?null:Arrays.asList(Long.valueOf(topUserId)));
    }

    //凌晨清除缓存
    public void cleanCache(){
        redisCache.deleteObject(CacheConstants.USER_GAME_RECORD_COUNT.concat("*"));
    }

    /**
     * 金额为负数则转为正数
     * */
    private double dealMoney(double money){
        return money<0?money*-1:money;
    }


    /**
     * 更新用户充值后是否满足流水
     *
     * */
    @DSTransactional
    public void calculationWithdraw(Long userId){
        if(null != userId && userId.longValue() == -1){
            userId = null;
        }
        //查询所有未满足提现的充值、转账
        String chargeType3 = FinTranType3.ON_LINE_CHARGE.getType() + "," + FinTranType3.CHARGE_IN.getType()+ "," + FinTranType3.CHARGE_IN_Back.getType()
                            + "," + FinTranType3.TRANSFER_TO_TEAM_DiamondCoin.getType();
        List<FinTranRecord> chargeList = finTranRecordService.selectUserTran(FinTranType1.U_Income_Coin_Balance.getType(),chargeType3,userId,null,null,0);
        if(null != chargeList && chargeList.size() > 0) {
            Map<Long, List<FinTranRecord>> chargeMap = chargeList.stream().collect(Collectors.groupingBy(FinTranRecord::getUid));
            for(Long uid:chargeMap.keySet()){
                List<FinTranRecord> userChargeList = chargeMap.get(uid);
                //按时间排序
                userChargeList = userChargeList.stream().sorted(Comparator.comparing(FinTranRecord::getCreateTime)).collect(Collectors.toList());
                Date beginDate= null;
                Double money = 0.00;//需要满足的投注流水
                Date endDate = new Date();
                int i = 1;
                List<FinTranRecord> dealTranList = new ArrayList<>();
                for (FinTranRecord tranRecord : userChargeList) {
                    dealTranList.add(tranRecord);
                    if (null == beginDate){
                        beginDate = tranRecord.getCreateTime();
                    }
                    if(userChargeList.size() > i){
                        endDate = new Date(userChargeList.get(i).getCreateTime().getTime() - 1);
                    }else{
                        endDate = new Date();
                    }
                    money += tranRecord.getDiamondCoinChange();
                    //查询赠送金额
                    AppUsersCharge appUsersCharge = appUsersChargeService.selectByOrderNo(String.valueOf(tranRecord.getTranGroupId()));
                    if(null != appUsersCharge && null != appUsersCharge.getCoinGive()){
                        money += appUsersCharge.getCoinGive().doubleValue();
                    }
                    dealTran(dealTranList,beginDate,endDate,uid,money);
                    i++;
                }


            }
        }
    }

    private void dealTran(List<FinTranRecord> userChargeList,Date beginDate,Date endDate,Long userId,Double money){
        //查询用户这段时间流水记录
        String type3s = FinTranType3.CONSUM_GAME_ANCHOR_ZHUANPAN.getType() + "," + FinTranType3.CONSUM_GAME_ANCHOR_WITHDRAW.getType();
        List<FinTranRecord> curTranList = finTranRecordService.selectUserTran(null,type3s,userId,beginDate,endDate,0);
        if(null != curTranList && curTranList.size() > 0){
            //筛选投注流水
            double bettingAmount = curTranList.stream().filter(e->
                    e.getTranType3().equals(FinTranType3.CONSUM_GAME_ANCHOR_ZHUANPAN.getType())
                            &&
                            e.getCurrencyType().intValue() == 4
            ).mapToDouble(FinTranRecord::getDiamondCoinChange).sum() * -1;
            if(bettingAmount >= money * 2){
                //更新为已满足提现
                userChargeList.forEach(e->{
                    FinTranRecord updateTran = new FinTranRecord();
                    updateTran.setId(e.getId());
                    updateTran.setWithdrawFlag(1);
                    finTranRecordService.updateFinTranRecord(updateTran);
                });
                //更新可提现余额
                updateWithdrawAble(userId);
            }
        }
    }

    /**
     * 更新用户可提现余额
     * */
    @DSTransactional
    public void updateWithdrawAble(Long userId){
        if(null != userId && userId.longValue() == -1){
            userId = null;
        }
        //查询所有未满足提现的充值、转账
        String chargeType3 = FinTranType3.ON_LINE_CHARGE.getType() + "," + FinTranType3.CHARGE_IN.getType()+ "," + FinTranType3.CHARGE_IN_Back.getType()
                + "," + FinTranType3.TRANSFER_TO_TEAM_DiamondCoin.getType();
        List<FinTranRecord> chargeList = finTranRecordService.selectUserTran(FinTranType1.U_Income_Coin_Balance.getType(),chargeType3,userId,null,null,1);
        if(null != chargeList && chargeList.size() > 0){
            Map<Long, List<FinTranRecord>> chargeMap = chargeList.stream().collect(Collectors.groupingBy(FinTranRecord::getUid));
            for(Long uid : chargeMap.keySet()) {
                int i = 1;
                double withdrawAble = 0;
                List<FinTranRecord> tranRecordList = chargeMap.get(uid);
                tranRecordList = tranRecordList.stream().sorted(Comparator.comparing(FinTranRecord::getCreateTime)).collect(Collectors.toList());
                Date beginDate = null;
                Date endDate = null;
                for (FinTranRecord finTranRecord : tranRecordList) {
                    if(null == beginDate) {
                        beginDate = finTranRecord.getCreateTime();
                    }
                    if (chargeList.size() > i) {
                        endDate = new Date(chargeList.get(i).getCreateTime().getTime() - 1);
                    }else{
                        //查询用户是否还有未满足提现的充值
                        List<FinTranRecord> curChargeList = finTranRecordService.selectUserTran(FinTranType1.U_Income_Coin_Balance.getType(),chargeType3,finTranRecord.getUid(),finTranRecord.getCreateTime(),null,0);
                        if(null != curChargeList && curChargeList.size() > 0){
                            endDate = curChargeList.get(0).getCreateTime();
                        }else{
                            endDate = new Date();
                        }

                    }
                    i++;

                }
                //查询用户这段时间流水记录
                List<FinTranRecord> curTranList = finTranRecordService.selectUserTran(null, null, uid, null, endDate, null);
                withdrawAble += curTranList.stream().filter(e->FinTranType3.CONSUM_GAME_ANCHOR_WITHDRAW.getType()!=e.getTranType3().intValue()).mapToDouble(FinTranRecord::getDiamondCoinChange).sum();
                AppUser updateUser = new AppUser();
                updateUser.setUserid(uid);
                updateUser.setWithdrawAble(withdrawAble);
                appUserService.updateAppUser(updateUser);
                //清除用户缓存
                redisCache.deleteObject("U:UserInfo:".concat(String.valueOf(uid)));
            }
        }
    }
}
