package cn.wisenergy.service.app.impl;

import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.common.utils.R;
import cn.wisenergy.mapper.*;
import cn.wisenergy.model.app.*;
import cn.wisenergy.model.enums.MemberPercentEnum;
import cn.wisenergy.model.enums.RebateStatusEnum;
import cn.wisenergy.model.enums.TradeRecordEnum;
import cn.wisenergy.model.enums.TradeStatusEnum;
import cn.wisenergy.model.vo.TeamPerformanceSortVo;
import cn.wisenergy.service.Manager.AccountManager;
import cn.wisenergy.service.Manager.PublicManager;
import cn.wisenergy.service.app.DayTaskService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @author 86187
 */
@Service
@Slf4j
public class DayTaskServiceImpl implements DayTaskService {
    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private MemberPercentMapper memberPercentMapper;

    @Autowired
    private AccountManager accountManager;

    @Autowired
    private PublicManager publicManager;

    @Autowired
    private TradeRecordMapper tradeRecordMapper;

    @Autowired
    private TeamPerformanceMapper teamPerformanceMapper;

    @Autowired
    private ProgressPrizeMapper progressPrizeMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private MonthManureMapper monthManureMapper;

    @Autowired
    private LastAccountMapper lastAccountMapper;

    private static final String PATTERN = "yyyy-MM";

    private static final Integer TWENTY = 20;

    @XxlJob(value = "orderRebateDayTask")
    @Override
    public R<Boolean> orderRebate() {
        log.info("订单返佣接口定时-日任务");
        //        //获取返佣订单
        List<OrderInfo> list = orderMapper.getListBySuccessTime(new Date());
        log.info("shop-mall[]AccountServiceImpl[]orderRebate[]input.param.list:{}", list.size());
        if (CollectionUtils.isEmpty(list)) {
            return R.ok(0, true);
        }

        //1、遍历订单，订单状态是未返佣，完成时间小于当前时间 --返佣
        for (OrderInfo orderInfo : list) {
            long successTime = orderInfo.getSuccessTime().getTime();
            long time = System.currentTimeMillis();
            if (RebateStatusEnum.NO_REBATE.getCode().equals(orderInfo.getRebateStatus()) && successTime <= time) {
                //获取用户信息
                User user = usersMapper.getByUserId(orderInfo.getUserId());
                if (null == user || user.getUserLevel() == 0) {
                    continue;
                }

                //获取账户信息
                AccountInfo accountInfo = accountMapper.getByUserId(user.getUserId());
                if (null == accountInfo) {
                    continue;
                }

                //获取返佣比例
                MemberPercent memberpercent = memberPercentMapper.getByLevelAndType(user.getUserLevel(),
                        MemberPercentEnum.REBATE.getCode());
                if (null == memberpercent) {
                    continue;
                }

                //修改订单状态为已返佣，账户可用金额增加
                accountManager.updateOrderAddMoney(orderInfo, accountInfo, memberpercent);
            }
        }
        return R.ok(0, true);
    }


    @XxlJob(value = "monthManureDayTask")
    @Override
    public R<Boolean> performanceCount() {
        //获取本月订单
        log.info("月度肥料定时-日任务开启");
        List<OrderInfo> list = orderMapper.getByCreateTime(new Date());
        log.info("shop-mall[]AccountServiceImpl[]performanceCount[]input.param.list:{}", list.size());
        if (CollectionUtils.isEmpty(list)) {
            return R.ok(0, true);
        }

        Date date = new Date();
        String yearMonth = DateUtil.convertDateToStr(date, PATTERN);

        //计算当月所有订单成交额
        BigDecimal totalMoney = new BigDecimal(0);

        //统计出出每个用户当月订单成交额 key:userId  value:用户当月订单成交额
        Map<String, Double> map = new HashMap<>();
        for (OrderInfo orderInfo : list) {
            String userId = orderInfo.getUserId();
            double payMoney = orderInfo.getPayment().doubleValue();

            //key 存在  累加订单金额 到 value
            if (map.containsKey(userId)) {
                double money = payMoney + map.get(orderInfo.getUserId());
                map.put(orderInfo.getUserId(), money);
            } else {
                //key 不存在，加入集合
                map.put(userId, payMoney);
            }
            totalMoney = totalMoney.add(orderInfo.getPayment());
        }

        //累计用户和上级用户-团队业绩
        Map<String, Double> tempMap = new HashMap<>();
        for (Map.Entry<String, Double> entity : map.entrySet()) {
            String userId = entity.getKey();
            //1)、统计当前用户月度业绩
            double userCount = entity.getValue();
            if (tempMap.containsKey(entity.getKey())) {
                double teamMoney = userCount + tempMap.get(entity.getKey());
                tempMap.put(entity.getKey(), teamMoney);
            } else {
                //key 不存在，加入集合 当前用户团队绩效
                tempMap.put(entity.getKey(), userCount);
            }

            //2)、获取当前用户的上级用户列表
            List<User> userList = getByList(userId);
            if (CollectionUtils.isEmpty(userList)) {
                continue;
            }

            for (User user : userList) {
                //3)、统计当前用户的上级用户团队绩效
                //key 存在  当前用户团队绩效  + 上级用户团队绩效
                if (tempMap.containsKey(user.getUserId())) {
                    double teamMoney = userCount + tempMap.get(user.getUserId());
                    tempMap.put(user.getUserId(), teamMoney);
                } else {
                    //key 不存在，加入集合 当前用户团队绩效
                    tempMap.put(user.getUserId(), userCount);
                }
            }
        }

        //3、获取用户当月绩效信息   新增 or 更新
        List<TeamPerformance> addList = new ArrayList<>();
        List<TeamPerformance> updateList = new ArrayList<>();
        for (Map.Entry<String, Double> entity : tempMap.entrySet()) {
            //获取团队业绩信息
            TeamPerformance teamPerformance = teamPerformanceMapper.getByUserIdAndTime(entity.getKey(), yearMonth);
            if (null == teamPerformance) {
                //获取用户信息
                User user = usersMapper.getByUserId(entity.getKey());

                //添加用户团队业绩信息
                TeamPerformance performance = new TeamPerformance();
                performance.setUserId(user.getUserId());
                performance.setMonthTeamPerformance(BigDecimal.valueOf(entity.getValue()));
                performance.setUserLevel(user.getUserLevel());
                performance.setYearMonth(yearMonth);
                addList.add(performance);
            } else {
                teamPerformance.setMonthTeamPerformance(BigDecimal.valueOf(entity.getValue()));
                updateList.add(teamPerformance);
            }
        }

        //4、更新账户月度团队业绩
        boolean updateBool = accountManager.updateAccountPerformanceMonth(addList, updateList);
        if (!updateBool) {
            return R.ok(1, false);
        }

        //5、获取所有用户,如果会员等级是黄金以上，计算月度收益
        List<User> userList = usersMapper.getAllGoldUser();
        if (CollectionUtils.isEmpty(userList)) {
            return R.ok(0, true);
        }

        //6、如果用户的团队业绩不存在的，新增本月团队业绩
        addTeamPerformance(userList);

        boolean bool = monthlyIncome(totalMoney, userList);
        if (!bool) {
            return R.ok(1, false);
        }
        log.info("月度肥料定时-日任务执行成功");
        return R.ok(0, true);
    }

    @XxlJob(value = "growthAwardDayTask")
    @Override
    public R<Boolean> progressPrizeCount() {
        log.info("shop-mall[]AccountServiceImpl[]performanceCount[]input.method");
        log.info("本月最大进步奖日定时任务开启");
        Date date = new Date();
        String yearMonth = DateUtil.convertDateToStr(date, PATTERN);

        //获取当月所有人业绩总额
        List<OrderInfo> orderList = orderMapper.getByCreateTime(new Date());
        if (CollectionUtils.isEmpty(orderList)) {
            return R.ok(0, true);
        }
        BigDecimal totalMoney = new BigDecimal(0);
        for (OrderInfo orderInfo : orderList) {
            totalMoney = totalMoney.add(orderInfo.getPayment());
        }
        double number = Math.floor(totalMoney.doubleValue() / 3980 / 12);
        if (number == 0) {
            return R.ok(0, true);
        }

        //1、判断当前月是否是业绩开始的第一个月
        List<TeamPerformance> teamPerformances = teamPerformanceMapper.getByBeforeTime(yearMonth);

        //2、集合为空 是业绩开始的第一个月
        if (CollectionUtils.isEmpty(teamPerformances)) {
            //获取月业绩前20用户
            List<TeamPerformance> list = teamPerformanceMapper.userTwenty(yearMonth);
            if (CollectionUtils.isEmpty(list)) {
                return R.ok(0, true);
            }

            //获取20名进步最大的月业绩和
            Double twentyTotal = teamPerformanceMapper.countTwenty(yearMonth);
            List<AccountInfo> accountInfoList = new ArrayList<>();
            List<TradeRecord> tradeRecordList = new ArrayList<>();
            List<ProgressPrize> addPrizeList = new ArrayList<>();
            List<ProgressPrize> updatePrizeList = new ArrayList<>();
            for (TeamPerformance user : list) {
                //获取最大进步奖 百分比
                MemberPercent memberPercent = memberPercentMapper.getByLevelAndType(user.getUserLevel(),
                        MemberPercentEnum.MONTH_BEST_AWARD.getCode());

                //计算收益
                double userTeamPerformance = user.getMonthTeamPerformance().doubleValue();
                double percent = memberPercent.getPercent().doubleValue();
                double income = Math.floor(number * 3980 * percent * userTeamPerformance / twentyTotal);

                //获取账户信息
                AccountInfo accountInfo = accountMapper.getByUserId(user.getUserId());

                //用户月收益  =其他收益+最大进步奖收益
                BigDecimal earningsMonth = accountInfo.getEarningsMonth().add(BigDecimal.valueOf(income));
                accountInfo.setEarningsMonth(earningsMonth);

                //用户总收益 =其他总收益 + 最大进步奖收益
                BigDecimal earningsTotal = accountInfo.getEarningsTotal().add(BigDecimal.valueOf(income));
                accountInfo.setEarningsTotal(earningsTotal);
                accountInfoList.add(accountInfo);

                //添加最大进步奖信息  不存在：新增   存在，修改
                BigDecimal awardMoney = new BigDecimal(income).setScale(2, RoundingMode.HALF_UP);
                ProgressPrize progressPrize = progressPrizeMapper.getByUserIdYearMonth(user.getUserId(), yearMonth);
                if (null == progressPrize) {
                    ProgressPrize prize = new ProgressPrize();
                    prize.setAwardMoney(awardMoney.doubleValue());
                    prize.setUserId(user.getUserId());
                    prize.setGrowthRate(0.0);
                    prize.setYearMonth(yearMonth);
                    addPrizeList.add(prize);
                } else {
                    progressPrize.setYearMonth(yearMonth);
                    progressPrize.setAwardMoney(awardMoney.doubleValue());
                    updatePrizeList.add(progressPrize);
                }

                //添加交易流水记录
                TradeRecord tradeRecord = new TradeRecord();
                tradeRecord.setUserId(user.getUserId());
                tradeRecord.setTradeType(TradeRecordEnum.PROGRESS_PRIZE.getCode());
                tradeRecord.setTradeNo(null);
                tradeRecord.setStatus(TradeStatusEnum.NO_SETTLE_ACCOUNTS.getCode());
                tradeRecord.setMoney(BigDecimal.valueOf(income));
                tradeRecordList.add(tradeRecord);
            }

            //更新账户信息，添加交易流水记录
            boolean bool = accountManager.updateAccountAddRecordAddPrize(accountInfoList, tradeRecordList,
                    addPrizeList, updatePrizeList);
            if (!bool) {
                return R.ok(1, false);
            }
            return R.ok(0, true);
        }

        //3、集合不为空 不是业绩开始的第一个月
        //获取用户列表
        List<User> userList = usersMapper.findAllNotZeroUser();
        if (CollectionUtils.isEmpty(userList)) {
            return R.ok(0, true);
        }

        //如果用户的团队业绩不存在的，新增本月团队业绩
        addTeamPerformance(userList);

        //4计算每个用户本月的业绩增长率  如果集合大于20 ，取前二十名，小于，取全部
        List<TeamPerformanceSortVo> listVo = progressPrizeStatistics(userList);
        if (listVo.size() >= TWENTY) {
            listVo.subList(0, TWENTY);
        }

        //5、计算前20的总业绩
        double total = listVo.stream().mapToDouble(TeamPerformanceSortVo::getMonthPerformance).sum();
        boolean bool = totalPerformanceIncome(listVo, number, total);
        if (!bool) {
            return R.ok(1, false);
        }
        log.info("本月最大进步奖日定时任务执行成功");
        return R.ok(0, true);
    }

    /**
     * 获取用户的上级列表
     *
     * @param userId 用户id
     * @return 用户的上级列表
     */
    @Override
    public List<User> getByList(String userId) {
        List<User> list = new ArrayList<>();
        User user = usersMapper.getByUserId(userId);
        getUser(list, userId);
        //去除本身
        list.remove(user);
        return list;
    }

    public void getUser(List<User> list, String userId) {
        User user = usersMapper.getByUserId(userId);
        if (null != user && !StringUtils.isBlank(user.getBeInvitedCode()) &&
                !"1".equals(user.getBeInvitedCode()) && !"88888888".equals(user.getBeInvitedCode())) {
            user = usersMapper.getByBeInvitedCode(user.getBeInvitedCode());
            list.add(user);
            getUser(list, user.getUserId());
        }
    }

    /**
     * 统计每个用户本月业绩增长率
     *
     * @param userList 用户列表
     * @return 每个用户本月业绩增长率
     */
    private List<TeamPerformanceSortVo> progressPrizeStatistics(List<User> userList) {
        Date date = new Date();
        String yearMonth = DateUtil.convertDateToStr(date, PATTERN);

        //遍历 计算业绩增长率
        List<TeamPerformanceSortVo> listVo = new ArrayList<>();
        for (User user : userList) {
            TeamPerformanceSortVo teamVo = new TeamPerformanceSortVo();
            double growthRate;
            //获取当月业绩
            TeamPerformance teamPerformance = teamPerformanceMapper.getByUserIdAndTime(user.getUserId(), yearMonth);

            //获取上月业绩
            Calendar cal = Calendar.getInstance();
            cal.setTime(new Date());
            cal.add(Calendar.MONTH, -1);
            Date lastDate = cal.getTime();
            String lastMonthTime = DateUtil.convertDateToStr(lastDate, PATTERN);
            TeamPerformance lastMonth = teamPerformanceMapper.getByUserIdAndTime(user.getUserId(), lastMonthTime);
            if (null == teamPerformance || null == lastMonth) {
                growthRate = 0.00;
            } else {
                double month = teamPerformance.getMonthTeamPerformance().doubleValue();
                double last = lastMonth.getMonthTeamPerformance().doubleValue();
                if (last >= month) {
                    growthRate = 0.00;
                } else if (last == 0) {
                    growthRate = 0.00;
                } else {
                    growthRate = (month - last) / last;
                }
            }
            BigDecimal grow = new BigDecimal(growthRate).setScale(2, RoundingMode.HALF_UP);
            teamVo.setGrowthRate(grow.doubleValue());
            double monthPerformance;
            assert teamPerformance != null;
            if (null == teamPerformance.getMonthTeamPerformance()) {
                monthPerformance = 0.00;
            } else {
                monthPerformance = teamPerformance.getMonthTeamPerformance().doubleValue();
            }
            teamVo.setMonthPerformance(monthPerformance);
            teamVo.setUserId(user.getUserId());
            teamVo.setTeamPerformance(teamPerformance);
            listVo.add(teamVo);
        }

        //对集合进行排序
        listVo.sort(Comparator.comparing(TeamPerformanceSortVo::getGrowthRate).reversed());
        return listVo;
    }

    /**
     * 如果会员等级是黄金以上，计算月度收益
     *
     * @param totalMoney 月金额总额
     * @param userList   用户列表
     * @return true or false
     */
    private boolean monthlyIncome(BigDecimal totalMoney, List<User> userList) {
        double total = totalMoney.doubleValue();
        Date date = new Date();
        String yearMonth = DateUtil.convertDateToStr(date, PATTERN);

        //当月所有人订单成交总金额/3980/12  向下整
        double moneyMonth = Math.floor(total / 3980 / 12);
        if (moneyMonth == 0) {
            return true;
        }

        List<AccountInfo> accountInfoList = new ArrayList<>();
        List<TradeRecord> tradeRecordList = new ArrayList<>();

        //获取上月未分配完的奖金
        double lastMonthAward;
        Date last = DateUtil.getLastMonth(new Date());
        String yearMonthTime = DateUtil.convertDateToStr(last, PATTERN);
        MonthManure monthManure = monthManureMapper.queryByTime(yearMonthTime);
        if (null == monthManure) {
            lastMonthAward = 0.00;
        } else {
            lastMonthAward = monthManure.getManureAward();
        }

        for (User user : userList) {
            //获取等级优惠百分比
            MemberPercent memberPercent = memberPercentMapper.getByLevelAndType(user.getUserLevel(), 2);
            if (null != memberPercent) {
                //获取本月团队总金额
                TeamPerformance teamPerformance = teamPerformanceMapper.getByUserIdAndTime(user.getUserId(), yearMonth);
                //获取该等级团队总金额
                Double teamTotal = teamPerformanceMapper.countTeamMoney(user.getUserLevel(), yearMonth);
                if (null != teamPerformance && null != teamTotal && teamTotal != 0) {
                    double month = teamPerformance.getMonthTeamPerformance().doubleValue();
                    double percent = memberPercent.getPercent().doubleValue();
                    //计算收益
                    double teamMoney = ((moneyMonth * 3980) + lastMonthAward) * percent * month;
                    double income = teamMoney / teamTotal;
                    if (income == 0) {
                        continue;
                    }

                    //获取账户信息
                    AccountInfo accountInfo = accountMapper.getByUserId(user.getUserId());
                    BigDecimal bigDecimal = new BigDecimal(income).setScale(2, RoundingMode.HALF_UP);

                    //获取本月培育奖信息
                    TradeRecord tradeRecordMonth = tradeRecordMapper.getByUserIdAndTypeAndStatus(user.getUserId(),
                            TradeRecordEnum.CULTIVATING_PRIZE.getCode(), new Date(), TradeStatusEnum.NO_SETTLE_ACCOUNTS.getCode());
                    BigDecimal tradeMoney = new BigDecimal(0);
                    if (null != tradeRecordMonth) {
                        tradeMoney = tradeRecordMonth.getMoney();
                    }

                    //获取用户本月收益=可提现金额+ 本月肥料收益+培育奖收益
                    BigDecimal performanceMonth = accountInfo.getExtractMoney().add(bigDecimal).add(tradeMoney);
                    accountInfo.setEarningsMonth(performanceMonth);

                    //获取用户上月总收益
                    LastMonthAccount lastMonthAccount = lastAccountMapper.getByUserIdAndTime(user.getUserId(), yearMonthTime);
                    BigDecimal lastTotalMonth;
                    if (null == lastMonthAccount || null == lastMonthAccount.getEarningsTotal()) {
                        lastTotalMonth = new BigDecimal("0.00");
                    } else {
                        lastTotalMonth = lastMonthAccount.getEarningsTotal();
                    }

                    //用户总收益=上月总收益+本月收益
                    BigDecimal performanceTotal = lastTotalMonth.add(performanceMonth);
                    accountInfo.setEarningsTotal(performanceTotal);
                    accountInfoList.add(accountInfo);

                    //5、添加交易流水记录
                    TradeRecord tradeRecord = new TradeRecord();
                    tradeRecord.setUserId(user.getUserId());
                    tradeRecord.setTradeType(TradeRecordEnum.MONTHLY_FERTILIZER.getCode());
                    tradeRecord.setTradeNo(null);
                    tradeRecord.setStatus(TradeStatusEnum.NO_SETTLE_ACCOUNTS.getCode());
                    tradeRecordList.add(tradeRecord);
                }
            }
        }
        //更新账户信息，新增交易流水记录
        return accountManager.updateAccountAddRecord(accountInfoList, tradeRecordList);
    }

    /**
     * 统计用户最大进步奖收益
     *
     * @param listVo 用户增长率列表
     * @param number 个人业绩
     * @param total  总业绩
     */
    private boolean totalPerformanceIncome(List<TeamPerformanceSortVo> listVo, double number, double total) {
        //要更新的账户列表
        List<AccountInfo> updateAccountList = new ArrayList<>();
        String yearMonth = DateUtil.convertDateToStr(new Date(), "yyyy-MM");

        List<ProgressPrize> addList = new ArrayList<>();
        List<ProgressPrize> updateList = new ArrayList<>();
        if (number > 0) {
            for (TeamPerformanceSortVo teamVo : listVo) {
                String userId = teamVo.getTeamPerformance().getUserId();
                Integer userLevel = teamVo.getTeamPerformance().getUserLevel();
                //获取最大进步奖 百分比
                MemberPercent memberPercent = memberPercentMapper.getByLevelAndType(userLevel, 3);

                //计算收益
                double userTeamPerformance = teamVo.getTeamPerformance().getMonthTeamPerformance().doubleValue();
                double percent = memberPercent.getPercent().doubleValue();
                double income = number * 3980 * percent * userTeamPerformance / total;

                //获取账户信息
                AccountInfo accountInfo = accountMapper.getByUserId(userId);
                //用户月收益  =其他收益+最大进步奖收益
                BigDecimal earningsMonth = accountInfo.getEarningsMonth().add(BigDecimal.valueOf(income));
                accountInfo.setEarningsMonth(earningsMonth);

                //用户总收益 =其他总收益 + 最大进步奖收益
                BigDecimal earningsTotal = accountInfo.getEarningsTotal().add(BigDecimal.valueOf(income));
                accountInfo.setEarningsTotal(earningsTotal);
                updateAccountList.add(accountInfo);

                //最大进步奖信息
                ProgressPrize progressPrize = progressPrizeMapper.getByUserIdYearMonth(userId, yearMonth);
                if (null == progressPrize) {
                    //新增
                    ProgressPrize addPrize = new ProgressPrize();
                    addPrize.setAwardMoney(income);
                    addPrize.setYearMonth(yearMonth);
                    addPrize.setGrowthRate(0.0);
                    addPrize.setUserId(userId);
                    addList.add(addPrize);
                } else {
                    progressPrize.setGrowthRate(teamVo.getGrowthRate());
                    progressPrize.setAwardMoney(income);
                    if (income > 0) {
                        progressPrize.setGrowthRate(teamVo.getGrowthRate());
                    } else {
                        progressPrize.setGrowthRate(0.0);
                    }
                    updateList.add(progressPrize);
                }
            }

            //获取本月已经存在的最大进步奖列表
            List<ProgressPrize> prizes = progressPrizeMapper.getByYearMonth(yearMonth);

            //修改或保存最大进步奖信息
            //  flag  1： 日定时任务  2：月定时任务
            int flag = 1;
            return accountManager.updateOrSavePrize(updateAccountList, prizes, addList, updateList, flag);
        }
        return true;
    }

    private void addTeamPerformance(List<User> userList) {
        String yearMonth = DateUtil.convertDateToStr(new Date(), "yyyy-MM");
        if (!CollectionUtils.isEmpty(userList)) {
            for (User user : userList) {
                //获取团队业绩信息
                TeamPerformance teamPerformance = teamPerformanceMapper.getByUserIdAndTime(user.getUserId(), yearMonth);
                if (null == teamPerformance) {
                    TeamPerformance addTeam = new TeamPerformance();
                    addTeam.setMonthTeamPerformance(new BigDecimal(0));
                    addTeam.setYearMonth(yearMonth);
                    addTeam.setUserLevel(user.getUserLevel());
                    addTeam.setUserId(user.getUserId());
                    teamPerformanceMapper.add(addTeam);
                }
            }
        }
    }
}
