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.PublicManager;
import cn.wisenergy.service.app.AccountService;
import cn.wisenergy.service.Manager.AccountManager;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.util.*;


/**
 * @author 86187
 */
@Slf4j
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, AccountInfo> implements AccountService {

    @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 LastAccountMapper lastAccountMapper;

    @Autowired
    private OrderMapper orderMapper;

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

    private static final Integer TWENTY = 20;

    @Override
    public R<Boolean> orderRebate() {

        //获取返佣订单
        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.getBuyerId());
                if (null == user) {
                    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);
    }

    @Override
    public R<AccountInfo> getByUserId(String userId) {
        AccountInfo accountInfo = accountMapper.getByUserId(userId);
        return R.ok(accountInfo);
    }

    @Override
    public R<Boolean> performanceCount(List<OrderInfo> list) {
        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);
        for (OrderInfo orderInfo : list) {
            //判断是否是本月
            boolean bool = publicManager.isThisMonth(orderInfo.getCreateTime(), PATTERN);
            if (bool && orderInfo.getMonthlyTaskStatus() == 0) {
                totalMoney = totalMoney.add(orderInfo.getPayment());
            }
        }

        //遍历订单  订单状态创建时间，当月时间小于当前时间
        for (OrderInfo orderInfo : list) {
            long createTime = orderInfo.getCreated().getTime();
            long time = System.currentTimeMillis();
            if (createTime <= time) {
                //获取用户信息
                User user = usersMapper.selectById(orderInfo.getBuyerId());
                if (null == user) {
                    continue;
                }

                List<TeamPerformance> teamPerformances = new ArrayList<>();

                //获取团队业绩信息
                TeamPerformance teamPerformance = teamPerformanceMapper.getByUserIdAndTime(user.getUserId(), yearMonth);
                if (null == teamPerformance) {
                    continue;
                }

                //1、统计当前用户月度业绩
                BigDecimal userCount = teamPerformance.getMonthTeamPerformance().add(orderInfo.getPayment());
                teamPerformance.setMonthTeamPerformance(userCount);
                teamPerformances.add(teamPerformance);

                //2、获取当前用户的上级用户列表 todo 邀请码等于一个固定值，停止 等于两个值  七位XXXXXXX 和 7777777
                List<User> userList = getByList(user.getUserId());
                if (CollectionUtils.isEmpty(userList)) {
                    continue;
                }

                for (User userInfo : userList) {
                    //3、统计当前用户上级月度绩效
                    TeamPerformance team = teamPerformanceMapper.getByUserIdAndTime(userInfo.getUserId(), yearMonth);
                    if (null == team) {
                        continue;
                    }
                    //1、统计当前用户月度绩效
                    BigDecimal monthCount = team.getMonthTeamPerformance().add(orderInfo.getPayment());
                    team.setMonthTeamPerformance(monthCount);
                    teamPerformances.add(team);
                }

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

        boolean bool = monthlyIncome(totalMoney, userList);
        if (!bool) {
            return R.ok(1, false);
        }
        return R.ok(0, true);

    }

    /**
     * 获取用户的商机信息
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public List<User> getByList(String userId) {
        List<User> list = new ArrayList<>();

        getUser(list, userId);

        return list;
    }

    @Override
    public R<Boolean> progressPrizeCount() {
        log.info("shop-mall[]AccountServiceImpl[]performanceCount[]input.method");
        Date date = new Date();
        String yearMonth = DateUtil.convertDateToStr(date, PATTERN);

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

        //获取当月所有人业绩总额
        Double totalMoney = teamPerformanceMapper.countByTime(yearMonth);
        double number = Math.floor(totalMoney / 3980 / 12);
        //2、集合为空 是业绩开始的第一个月
        if (CollectionUtils.isEmpty(teamPerformances)) {
            if (number != 0) {
                //获取月业绩前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<>();
                for (TeamPerformance user : list) {
                    //获取最大进步奖 百分比
                    MemberPercent memberPercent = memberPercentMapper.getByLevelAndType(user.getUserLevel(), 3);

                    //计算收益
                    double userTeamPerformance = user.getMonthTeamPerformance().doubleValue();
                    double percent = memberPercent.getPercent().doubleValue();

                    double income = number * 3980 * percent * userTeamPerformance / twentyTotal;

                    //获取账户信息
                    AccountInfo accountInfo = accountMapper.getByUserId(user.getUserId());
                    accountInfo.setEarningsMonth(new BigDecimal(income));
                    accountInfoList.add(accountInfo);

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

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

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

        //4计算每个用户本月的业绩增长率
        List<TeamPerformanceSortVo> listVo = progressPrizeStatistics(userList);

        //5、如果集合大于20 ，取前二十名，小于，取全部
        if (listVo.size() >= TWENTY) {
            //取排名前20的
            listVo.subList(0, TWENTY);

            //计算前20的总业绩
            double total = listVo.stream().mapToDouble(TeamPerformanceSortVo::getMonthPerformance).sum();
            totalPerformanceIncome(listVo, number, total);
            return R.ok(0, true);
        } else {
            //计算用户数少于20的总业绩
            double total = listVo.stream().mapToDouble(TeamPerformanceSortVo::getMonthPerformance).sum();
            totalPerformanceIncome(listVo, number, total);
        }
        return R.ok(0, true);
    }

    @Override
    public void mirrorImage() {
        //1、把账户表account_info复制给表account_image  CREATE TABLE table_2  SELECT * FROM table_1;
        lastAccountMapper.copyTable("account_info", "account_image");

        //删除上月备份
        lastAccountMapper.deleteTable("account_backup");

        //备份
        lastAccountMapper.copyTable("account_info", "account_backup");

        //2、把上月账户表last_month_account 复制给month_account_image
        lastAccountMapper.copyTable("last_month_account", "month_account_image");

        //3、删除last_month_account
        lastAccountMapper.deleteTable("last_month_account");

        //4、把account_image 更名为 last_month_account  rename table table_2 to table_1;
        lastAccountMapper.updateTableName("account_image", "last_month_account");

        //5、删除month_account_image   DROP table table_2;
        lastAccountMapper.deleteTable("month_account_image");
    }

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

    /**
     * 如果会员等级是黄金以上，计算月度收益
     *
     * @param totalMoney 月金额总额
     * @param userList   用户列表
     * @return
     */
    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);
        List<AccountInfo> accountInfoList = new ArrayList<>();
        List<TradeRecord> tradeRecordList = new ArrayList<>();
        for (User user : userList) {
            if (moneyMonth != 0) {
                //获取等级优惠百分比
                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) {
                        double month = teamPerformance.getMonthTeamPerformance().doubleValue();
                        double percent = memberPercent.getPercent().doubleValue();
                        //计算收益
                        double income = moneyMonth * 3980 * percent * month / teamTotal;

                        //获取账户信息
                        AccountInfo accountInfo = accountMapper.getByUserId(user.getUserId());
                        BigDecimal bigDecimal = new BigDecimal(income);
                        BigDecimal performanceMonth = accountInfo.getEarningsMonth().add(bigDecimal);
                        accountInfo.setEarningsMonth(performanceMonth);

                        BigDecimal performanceTotal = accountInfo.getEarningsMonth().add(bigDecimal);
                        accountInfo.setEarningsMonth(performanceTotal);
                        accountInfoList.add(accountInfo);


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

    /**
     * 统计每个用户本月业绩增长率
     *
     * @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 {
                    growthRate = (month - last) / month;
                }
            }
            teamVo.setGrowthRate(growthRate);
            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 listVo 用户增长率列表
     * @param number 个人业绩
     * @param total  总业绩
     */
    private void totalPerformanceIncome(List<TeamPerformanceSortVo> listVo, double number, double total) {
        //要更新的账户列表
        List<AccountInfo> updateAccountList = new ArrayList<>();

        BigDecimal sum = new BigDecimal(0);
        for (int i = 0; i < listVo.size(); i++) {
            String userId = listVo.get(i).getTeamPerformance().getUserId();
            Integer userLevel = listVo.get(i).getTeamPerformance().getUserLevel();
            //获取最大进步奖 百分比
            MemberPercent memberPercent = memberPercentMapper.getByLevelAndType(userLevel, 3);

            //计算收益
            double userTeamPerformance = listVo.get(i).getTeamPerformance().getMonthTeamPerformance().doubleValue();
            double percent = memberPercent.getPercent().doubleValue();

            double income = number * 3980 * percent * userTeamPerformance / total;

            //获取账户信息
            AccountInfo accountInfo = accountMapper.getByUserId(userId);
            BigDecimal bigDecimal;
            if (i == listVo.size() - 1) {
                bigDecimal = new BigDecimal(total).subtract(sum);
            } else {
                bigDecimal = accountInfo.getEarningsMonth().add(new BigDecimal(income));
                sum = sum.add(new BigDecimal(income));
            }
            accountInfo.setEarningsMonth(bigDecimal);
            updateAccountList.add(accountInfo);
        }

        //判断本月是否有最大进步奖数据 无，新增  有，修改或删除
        Date date = new Date();
        String yearMonth = DateUtil.convertDateToStr(date, PATTERN);
        List<ProgressPrize> prizes = progressPrizeMapper.getByYearMonth(yearMonth);

        //修改或保存最大进步奖信息
        accountManager.updateOrSavePrize(listVo, updateAccountList, prizes);
    }
}
