package cn.wisenergy.service.Manager;

import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.mapper.*;
import cn.wisenergy.model.app.*;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 86187
 * @ Description: 账户管理公共类
 * @ Author     : 86187
 * @ Date       : 2021/2/23 10:43
 */
@Component
@Slf4j
public class AccountManager {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private TradeRecordMapper recordMapper;

    @Autowired
    private TeamPerformanceMapper teamPerformanceMapper;

    @Autowired
    private ProgressPrizeMapper progressPrizeMapper;

    @Autowired
    private TradeRecordMapper tradeRecordMapper;


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


    /**
     * 保存用户佣金
     *
     * @param orderInfo     订单信息
     * @param accountInfo   账户信息
     * @param memberPercent 会员等级百比分
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderAddMoney(OrderInfo orderInfo, AccountInfo accountInfo, MemberPercent memberPercent) {
        //1、计算返佣金额
        BigDecimal bigDecimal = orderInfo.getPayment().multiply(memberPercent.getPercent());
        BigDecimal extractMoney = accountInfo.getExtractMoney().add(bigDecimal);
        extractMoney.setScale(2, RoundingMode.HALF_UP);
        accountInfo.setExtractMoney(extractMoney);

        BigDecimal performanceMonth = accountInfo.getEarningsMonth().add(bigDecimal);
        performanceMonth.setScale(2, RoundingMode.HALF_UP);
        accountInfo.setEarningsMonth(performanceMonth);

        BigDecimal performanceTotal = accountInfo.getEarningsMonth().add(bigDecimal);
        performanceTotal.setScale(2, RoundingMode.HALF_UP);
        accountInfo.setEarningsTotal(performanceTotal);

        //2、修改订单返佣状态：已返佣 1
        orderInfo.setRebateStatus(RebateStatusEnum.ALREADY_REBATE.getCode());

        orderMapper.updateById(orderInfo);

        //3、更新账户可用金额
        accountMapper.edit(accountInfo);

        //4、添加交易流水记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setUserId(orderInfo.getBuyerId());
        tradeRecord.setTradeType(TradeRecordEnum.ORDER_REBATE.getCode());
        tradeRecord.setTradeNo(orderInfo.getTid());
        tradeRecord.setStatus(TradeStatusEnum.ALREADY_SETTLE_ACCOUNTS.getCode());
        recordMapper.add(tradeRecord);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateAccountPerformanceMonth(List<TeamPerformance> list) {
        for (TeamPerformance teamPerformance : list) {
            teamPerformanceMapper.updateById(teamPerformance);
        }
    }

    /**
     * 修改 或新增  删除 最大进步奖实体类
     *
     * @param listVo          最新的进步奖 对象
     * @param accountInfoList 要更新的最大进步奖账户收益
     * @param prizes          上一次统计的进步奖 对象
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateOrSavePrize(List<TeamPerformanceSortVo> listVo, List<AccountInfo> accountInfoList, List<ProgressPrize> prizes) {

        Date date = new Date();
        String yearMonth = DateUtil.convertDateToStr(date, PATTERN);
        //构造一个map   key:userId  value progressPrize
        Map<String, ProgressPrize> map = new HashMap<>(32);
        for (ProgressPrize progressPrize : prizes) {
            map.put(progressPrize.getUserId(), progressPrize);
        }

        //1、判断 prizes 是否为空集合，是新增
        //新增
        if (CollectionUtils.isEmpty(prizes)) {
            for (TeamPerformanceSortVo sortVo : listVo) {
                String userId = sortVo.getTeamPerformance().getUserId();
                ProgressPrize progressPrize = new ProgressPrize();
                progressPrize.setUserId(userId);
                progressPrize.setGrowthRate(sortVo.getGrowthRate());
                progressPrize.setAwardMoney(sortVo.getMonthPerformance());
                progressPrize.setYearMonth(yearMonth);
                int count = progressPrizeMapper.add(progressPrize);
                if (count == 0) {
                    return false;
                }
            }
        } else {
            //2、不为空。存在的修改，不存在的新增，多余的，删除
            List<ProgressPrize> updateList = new ArrayList<>();
            List<ProgressPrize> addList = new ArrayList<>();
            List<String> userIds = prizes.stream().map(ProgressPrize::getUserId).collect(Collectors.toList());

            //遍历  筛选出要修改、新增、删除 对象
            for (TeamPerformanceSortVo sortVo : listVo) {
                if (userIds.contains(sortVo.getUserId())) {
                    //修改
                    ProgressPrize prize = map.get(sortVo.getUserId());
                    prize.setGrowthRate(sortVo.getGrowthRate());
                    prize.setAwardMoney(sortVo.getMonthPerformance());
                    updateList.add(prize);
                    //移除要修改的
                    prizes.remove(prize);
                } else {
                    //新增
                    String userId = sortVo.getTeamPerformance().getUserId();
                    ProgressPrize progress = new ProgressPrize();
                    progress.setUserId(userId);
                    progress.setGrowthRate(sortVo.getGrowthRate());
                    progress.setAwardMoney(sortVo.getMonthPerformance());
                    progress.setYearMonth(yearMonth);
                    addList.add(progress);
                }
            }
            List<ProgressPrize> deleteList = new ArrayList<>(prizes);

            for (ProgressPrize updatePrize : updateList) {
                int count = progressPrizeMapper.edit(updatePrize);
                if (count == 0) {
                    return false;
                }
            }

            for (ProgressPrize addPrize : addList) {
                int count = progressPrizeMapper.add(addPrize);
                if (count == 0) {
                    return false;
                }
            }

            for (ProgressPrize deletePrize : deleteList) {
                int count = progressPrizeMapper.delById(deletePrize.getId());
                if (count == 0) {
                    return false;
                }
            }
        }

        //3、添加账户获得的收益
        for (AccountInfo accountInfo : accountInfoList) {
            accountMapper.edit(accountInfo);

            //添加交易流水记录
            TradeRecord tradeRecord = new TradeRecord();
            tradeRecord.setUserId(accountInfo.getUserId());
            tradeRecord.setTradeType(TradeRecordEnum.PROGRESS_PRIZE.getCode());
            tradeRecord.setTradeNo(null);
            tradeRecord.setStatus(TradeStatusEnum.ALREADY_SETTLE_ACCOUNTS.getCode());
            int count = recordMapper.add(tradeRecord);
            if (count == 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * 更新账户信息和保存交易流水记录
     *
     * @param accountInfoList 账户列表
     * @param recordList      交易流水信息
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateAccountAddRecord(List<AccountInfo> accountInfoList, List<TradeRecord> recordList) {

        //更新月收益
        if (!CollectionUtils.isEmpty(accountInfoList)) {
            for (AccountInfo accountInfo : accountInfoList) {
                int count = accountMapper.updateById(accountInfo);
                if (count == 0) {
                    return false;
                }
            }
        }

        //新增交易流水记录
        if (!CollectionUtils.isEmpty(recordList)) {
            for (TradeRecord tradeRecord : recordList) {
                int count = tradeRecordMapper.add(tradeRecord);
                if (count == 0) {
                    return false;
                }
            }
        }
        return true;
    }
}
