package com.github.wxiaoqi.security.admin.biz;

import com.github.wxiaoqi.security.admin.bo.UserIncomeBo;
import com.github.wxiaoqi.security.admin.bo.UserStaffBo;
import com.github.wxiaoqi.security.admin.dto.*;
import com.github.wxiaoqi.security.admin.entity.*;
import com.github.wxiaoqi.security.admin.entity.AppUserRelation;
import com.github.wxiaoqi.security.admin.vo.SellingWalletVo;
import com.github.wxiaoqi.security.admin.vo.SellingWalletPagVo;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.wxiaoqi.security.admin.mapper.AppUserSellingWaterMapper;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 拥金明细表
 *
 * @author zjw
 * @email 18178966185@163.com
 * @date 2019-07-11 14:14:54
 */
@Service
@Slf4j
public class AppUserSellingWaterBiz extends BaseBiz<AppUserSellingWaterMapper, AppUserSellingWater> {


    @Autowired
    AppUserRelationBiz relationBiz;

    @Autowired
    BaseGoodCommissionBiz commissionBiz;

    @Autowired
    AppUserPositionBiz positionBiz;

    @Autowired
    AppUserDetailBiz detailBiz;

    @Autowired
    private AppUserLoginBiz appUserLoginBiz;

    @Autowired
    private AppUserDetailBiz appUserDetailBiz;

    @Autowired
    MyWaterBiz myWaterBiz;


    //计算用户拥金
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void orderWater(OrderWaterDTO orderWaterDTO) {
        if (orderWaterDTO == null) {
            log.info("计算用户拥金----orderWater----次数不能为空----");
            return;
        }
        //订单状态
        Integer status = orderWaterDTO.getStatus();
        if (status == null || status == 0) {
            log.info("购买计算用户拥金----payOrderWater----参数不能为空----status===" + status);
            return;
        }
        if (status == 1) {
            payOrderWater(orderWaterDTO);
        } else if (status == 2) {
            finishOrderWater(orderWaterDTO);
        } else {
            refundOrderWater(orderWaterDTO);
        }
    }

    //购买计算用户拥金
    public void payOrderWater(OrderWaterDTO orderWaterDTO) {
        //订单id
        Integer orderId = orderWaterDTO.getOrderId();
        //订单号
        String orderNo = orderWaterDTO.getOrderNo();
        //用户id
        Integer userId = orderWaterDTO.getUserId();
        List<OrderGoodsDTO> goodsDTOList = orderWaterDTO.getGoodsDTOList();
        log.info("购买计算用户拥金----payOrderWater----userId====" + userId + "---orderId===" + orderId + "---orderNo===" + orderNo);
        if (orderId == null || orderId == 0 || userId == null || userId == 0 | CollectionUtils.isEmpty(goodsDTOList)) {
            log.info("购买计算用户拥金----payOrderWater----参数不能为空----orderId===" + orderId);
            return;
        }
        AppUserRelation relation = relationBiz.getRelationByIdUserIdAndTime(userId);
        if (relation == null || relation.getParentId() == null || relation.getParentId() == 0) {
            log.info("购买计算用户拥金----payOrderWater--------userId===" + userId + "---无有效上线");
            return;
        }

        Integer parentId = relation.getParentId();
        log.info("购买计算用户拥金----payOrderWater--------userId===" + userId + "---parentId===" + parentId);
        Integer positionId = 6;
        Integer level = 0;
        AppUserPosition position = positionBiz.getExtract(parentId);
        if (position != null) {
            positionId = position.getId();
        }
        AppUserPosition position1 = positionBiz.getExtract(userId);
        if (position != null) {
            level = position1.getLevel();
        }
        log.info("购买计算用户拥金----payOrderWater--------userId===" + userId + "---positionId===" + positionId + "---level===" + level);
        if (level != 0) {
            log.info("购买计算用户拥金----payOrderWater--------userId===" + userId + "----无法享受拥金");
            return;
        }
        BigDecimal amount = new BigDecimal("0.00");
        //商品类型
        Integer orderType = 0;
        for (OrderGoodsDTO goodsDto : goodsDTOList) {
            //商品id
            Integer goodId = goodsDto.getGoodId();
            //商品价格
            BigDecimal price = goodsDto.getPrice();

            orderType = goodsDto.getType();
            //商品比例
            Integer extract = commissionBiz.getExtract(orderType, goodId);

            if (extract == null || extract == 0) {
                extract = position.getExtract();
            }
            log.info("购买计算用户拥金----payOrderWater--------userId===" + userId + "---extract===" + extract);
            if (extract != null && extract > 0) {
                AppUserSellingWater sellingWater = new AppUserSellingWater();
                sellingWater.setOrderId(orderId);
                sellingWater.setGoodId(goodId);
                sellingWater = selectOne(sellingWater);
                if (sellingWater != null) {
                    continue;
                }
                BigDecimal commission = price.multiply(new BigDecimal(extract + "")).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
                log.info("购买计算用户拥金----payOrderWater--------userId===" + userId + "---commission===" + commission);
                sellingWater = new AppUserSellingWater();
                sellingWater.setUserId(parentId);
                sellingWater.setSourceId(userId);
                sellingWater.setPositionId(positionId);
                sellingWater.setOrderId(orderId);
                sellingWater.setOrderNo(orderNo);
                sellingWater.setOrderType(orderType);
                sellingWater.setGoodId(goodId);
                sellingWater.setTitle(goodsDto.getTitle());
                sellingWater.setImg(goodsDto.getImg());
                sellingWater.setPrice(price);
                sellingWater.setExtract(extract);
                sellingWater.setGoodNumber(goodsDto.getGoodNumber());
                sellingWater.setCommission(commission);
                insertSelective(sellingWater);
                log.info("购买计算用户拥成功----payOrderWater--------userId===" + userId);
                amount = amount.add(commission);
            }
        }
        log.info("购买计算用户未入账----payOrderWater--------userId===" + parentId + "----amount====" + amount + "--orderType===" + orderType);
        if (orderType == 3) {
            finishOrderWater(orderWaterDTO);
        } else if (orderType == 1 || orderType == 2) {
            myWaterBiz.updMyWalletUnbooked(parentId, amount, 1);
        }
    }

    //订单完成计算用户拥金
    public void finishOrderWater(OrderWaterDTO orderWaterDTO) {
        //订单id
        Integer orderId = orderWaterDTO.getOrderId();
        log.info("订单完成计算用户拥金----finishOrderWater----orderId====" + orderId);
        if (orderId == null || orderId == 0) {
            return;
        }
        List<AppUserSellingWater> list = getWaterList(orderId);
        BigDecimal amount = new BigDecimal("0.00");
        Integer userId = 0;
        Integer orderType = 0;
        String orderNo = "";
        if (list.size() > 0) {
            orderNo = list.get(0).getOrderNo();
            for (AppUserSellingWater sellingWater : list) {
                Integer id = sellingWater.getId();
                orderType = sellingWater.getOrderType();
                userId = sellingWater.getUserId();
                sellingWater.setWaiting(1);
                updateById(sellingWater);
                BigDecimal commission = sellingWater.getCommission();
                log.info("订单完成计算用户拥金----finishOrderWater----id====" + id + "---commission==" + commission + "----orderType===" + orderType);
                amount = amount.add(commission);

            }
            BigDecimal unbooked = amount;
            log.info("订单完成计算用户拥金----finishOrderWater----orderId====" + orderId + "---amount==" + amount + "---unbooked==" + unbooked);
            if (orderType == 1) {
                List<OrderGoodsDTO> goodsDTOList = orderWaterDTO.getGoodsDTOList();
                log.info("租车订单完成-----goodsDTOList===" + goodsDTOList);
                if (CollectionUtils.isNotEmpty(goodsDTOList)) {
                    for (OrderGoodsDTO goodsDto : goodsDTOList) {
                        //商品id
                        Integer goodId = goodsDto.getGoodId();
                        //商品价格
                        BigDecimal price = goodsDto.getPrice();
                        AppUserSellingWater sellingWater = new AppUserSellingWater();
                        sellingWater.setOrderId(orderId);
                        sellingWater.setGoodId(goodId);
                        sellingWater = selectOne(sellingWater);
                        if (sellingWater == null || sellingWater.getExtract() == null || sellingWater.getExtract() == 0) {
                            log.info("租车订单完成-----sellingWater---不存在或extract---为空");
                            continue;
                        }
                        if (price.compareTo(sellingWater.getPrice()) >= 0) {
                            log.info("租车订单完成-----完成价格大于支付价格");
                            continue;
                        }
                        price = sellingWater.getPrice().subtract(price);
                        Integer extract = sellingWater.getExtract();
                        log.info("租车订单完成-----price=====" + price + "---extract====" + extract);
                        BigDecimal commission = price.multiply(new BigDecimal(extract + "")).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
                        log.info("租车订单完成--------userId===" + userId + "---commission===" + commission);
                        sellingWater.setWaiting(1);
                        sellingWater.setStatus(1);
                        sellingWater.setCommission(commission);
                        sellingWater.setId(null);
                        insertSelective(sellingWater);
                        log.info("租车订单完成计算用户拥成功----payOrderWater--------userId===" + userId);
                        amount = amount.subtract(commission);
                    }
                }
            }
            log.info("订单完成计算用户拥金----finishOrderWater--------orderId===" + orderId + "----amount====" + amount + "--orderType===" + orderType);
            int r = amount.compareTo(BigDecimal.ZERO);
            //更新钱包
            if (r == 1 && userId > 0) {
                MyWalletDetail detail = new MyWalletDetail();
                detail.setUserId(userId);
                detail.setAmount(amount);
                detail.setCono(orderId);
                detail.setWithDrawOrderNo(orderNo);
                detail.setSource(1);
                myWaterBiz.updMyWater(detail);
            }
            if ((orderType == 1 || orderType == 2) && unbooked.compareTo(BigDecimal.ZERO) == 1) {
                myWaterBiz.updMyWalletUnbooked(userId, unbooked, 2);
            }
        }


    }

    //订单退款计算用户拥金
    public void refundOrderWater(OrderWaterDTO orderWaterDTO) {
        //订单id
        Integer orderId = orderWaterDTO.getOrderId();
        log.info("订单完成计算用户拥金----refundOrderWater----orderId====" + orderId);
        if (orderId == null || orderId == 0) {
            return;
        }
        List<AppUserSellingWater> list = getWaterList(orderId);
        BigDecimal amount = new BigDecimal("0.00");
        BigDecimal unbooked = new BigDecimal("0.00");
        Integer userId = 0;
        Integer orderType = 0;
        String orderNo = "";
        if (list.size() > 0) {
            orderNo = list.get(0).getOrderNo();
            for (AppUserSellingWater sellingWater : list) {
                Integer id = sellingWater.getId();
                orderType = sellingWater.getOrderType();
                userId = sellingWater.getUserId();
                sellingWater.setWaiting(1);
                updateById(sellingWater);
                sellingWater.setId(null);
                sellingWater.setStatus(1);
                insertSelective(sellingWater);
                BigDecimal commission = sellingWater.getCommission();
                log.info("订单完成计算用户拥金----refundOrderWater----id====" + id + "---commission==" + commission + "---orderType====" + orderType);
                unbooked = unbooked.add(commission);
            }
            log.info("订单完成计算用户拥金----refundOrderWater----orderId====" + orderId + "---amount==" + amount + "---unbooked===" + unbooked);
            int r = amount.compareTo(BigDecimal.ZERO);
            //更新钱包
            if (r == 1 && userId > 0) {
                MyWalletDetail detail = new MyWalletDetail();
                detail.setUserId(userId);
                detail.setAmount(amount);
                detail.setCono(orderId);
                detail.setWithDrawOrderNo(orderNo);
                detail.setSource(1);
                myWaterBiz.updMyWater(detail);
            }
            if (orderType == 1 || orderType == 2) {
                myWaterBiz.updMyWalletUnbooked(userId, unbooked, 2);
            }
        }

    }


    //获取拥金列表
    public List<AppUserSellingWater> getWaterList(Integer orderId) {
        Example example = new Example(AppUserSellingWater.class);
        example.createCriteria().andEqualTo("orderId", orderId).andEqualTo("waiting", 0).andEqualTo("status", 0);
        return mapper.selectByExample(example);

    }


    public PageDataVO<UserIncomeBo> findMemberIdAndIncomeMapByMemberIds(Integer parentId, Integer pageNo, Integer pageSize) {
        return PageDataVO.pageInfo(pageNo, pageSize, () -> mapper.accquireIncomeByMemberIds(parentId));
    }

    public SellingWalletPagVo findSellingWaterPageByWaiting(Integer waiting, Integer userId, Integer pageNo, Integer pageSize) {

        SellingWalletPagVo sellingWalletPagVo = new SellingWalletPagVo();
        Example example = new Example(AppUserSellingWater.class);
        example.setOrderByClause("crt_time DESC");
        Example.Criteria criteria = example.createCriteria();
        if (waiting != null) {
            criteria.andEqualTo("waiting", waiting);
        }
        criteria.andEqualTo("userId", userId);
        PageDataVO<AppUserSellingWater> appUserSellingWaterPageDataVO = PageDataVO.pageInfo(pageNo, pageSize, () -> mapper.selectByExample(example));
        List<AppUserSellingWater> appUserSellingWaters = appUserSellingWaterPageDataVO.getData();
        if (CollectionUtils.isEmpty(appUserSellingWaters)) {
            sellingWalletPagVo.setPageNum(pageNo);
            sellingWalletPagVo.setPageSize(pageSize);
            sellingWalletPagVo.setTotalCount(0);
            sellingWalletPagVo.setTotalPage(0);
            sellingWalletPagVo.setTotalIncome(new BigDecimal(0));
            sellingWalletPagVo.setSellingWaters(Collections.EMPTY_LIST);
            return sellingWalletPagVo;
        }

        List<Integer> memberIds = appUserSellingWaters.stream().map(AppUserSellingWater::getSourceId).distinct().collect(Collectors.toList());

        Map<Integer, AppUserLogin> userIdAndAppUserLoginMap = appUserLoginBiz.findUserIdAndUserLoginMapByMemberIds(memberIds);
        Map<Integer, AppUserDetail> userIdAndAppUserDetailMap = appUserDetailBiz.findUserIdAndUserDetailMapByMemberIds(memberIds);

        List<SellingWalletVo> sellingWaterVos = new ArrayList<>();
        SellingWalletVo sellingWaterVo;
        BigDecimal totalIncome = new BigDecimal(0);
        for (AppUserSellingWater appUserSellingWater : appUserSellingWaters) {
            sellingWaterVo = new SellingWalletVo();
            BeanUtils.copyProperties(appUserSellingWater, sellingWaterVo);

            sellingWaterVo.setUsername(userIdAndAppUserLoginMap.get(appUserSellingWater.getSourceId()).getUsername());
            if (userIdAndAppUserDetailMap != null) {
                AppUserDetail appUserDetail = userIdAndAppUserDetailMap.get(appUserSellingWater.getSourceId());
                sellingWaterVo.setNickName(appUserDetail == null ? "" : appUserDetail.getNickname());
                sellingWaterVo.setHeadUrl(appUserDetail == null ? "" : appUserDetail.getHeadimgurl());
            }
            totalIncome = totalIncome.add(sellingWaterVo.getCommission());
            sellingWaterVos.add(sellingWaterVo);
        }
        if (waiting == null) {
            Supplier<Stream<AppUserSellingWater>> commissionStream = () -> appUserSellingWaters.stream();
            BigDecimal total = commissionStream.get().filter(x -> x.getStatus() == 0).map(AppUserSellingWater::getCommission).reduce(new BigDecimal(0), (x, y) -> x.add(y));
            BigDecimal refund = commissionStream.get().filter(x -> x.getStatus() == 1).map(AppUserSellingWater::getCommission).reduce(new BigDecimal(0), (x, y) -> x.add(y));
            totalIncome = total.subtract(refund);
        }

        sellingWaterVos.sort(Comparator.comparing(SellingWalletVo::getCrtTime).reversed());
        sellingWalletPagVo.setPageNum(pageNo);
        sellingWalletPagVo.setPageSize(pageSize);
        sellingWalletPagVo.setTotalCount(appUserSellingWaterPageDataVO.getTotalCount().intValue());
        sellingWalletPagVo.setTotalPage(appUserSellingWaterPageDataVO.getTotalPage());
        sellingWalletPagVo.setTotalIncome(totalIncome);
        sellingWalletPagVo.setSellingWaters(sellingWaterVos);

        return sellingWalletPagVo;
    }

    public BigDecimal selectTotalIncomeByUserId(Integer userId) {
        return mapper.selectTotalIncomeByUserId(userId);
    }

    public void deleteByMemberIds(Collection<Integer> userIds) {
        Example example = new Example(AppUserSellingWater.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.orIn("sourceId", userIds);
        criteria.orIn("userId", userIds);
        mapper.deleteByExample(example);
    }

    public SellingWalletPagVo findSellingWaterPageForAppByWaiting(Integer wating, Integer userId, Integer pageNo, Integer pageSize) {
        SellingWalletPagVo sellingWalletPagVo = new SellingWalletPagVo();
        PageDataVO<SellingWalletVo> pageDataVO = PageDataVO.pageInfo(pageNo, pageSize, () -> mapper.selectSellerWalterByUserIdAndWating(userId, wating));
        List<SellingWalletVo> data = pageDataVO.getData();
        if (CollectionUtils.isEmpty(data)) {
            sellingWalletPagVo.setPageNum(pageNo);
            sellingWalletPagVo.setPageSize(pageSize);
            sellingWalletPagVo.setSellingWaters(Collections.EMPTY_LIST);
            sellingWalletPagVo.setTotalCount(0);
            sellingWalletPagVo.setTotalPage(0);
            return sellingWalletPagVo;
        }

        List<Integer> memberIds = data.stream().map(SellingWalletVo::getSourceId).distinct().collect(Collectors.toList());
        Map<Integer, AppUserLogin> userIdAndAppUserLoginMap = appUserLoginBiz.findUserIdAndUserLoginMapByMemberIds(memberIds);
        Map<Integer, AppUserDetail> userIdAndAppUserDetailMap = appUserDetailBiz.findUserIdAndUserDetailMapByMemberIds(memberIds);

        for (SellingWalletVo sellingWalletVo : data) {
            String username = userIdAndAppUserLoginMap.get(sellingWalletVo.getSourceId()).getUsername();
            sellingWalletVo.setUsername(username);
            if (userIdAndAppUserDetailMap != null) {
                AppUserDetail appUserDetail = userIdAndAppUserDetailMap.get(sellingWalletVo.getSourceId());
                sellingWalletVo.setNickName(appUserDetail == null ? "" : appUserDetail.getRealname());
                sellingWalletVo.setHeadUrl(appUserDetail == null ? "" : appUserDetail.getHeadimgurl());
            }
            //取消单
            if (sellingWalletVo.getSellerStatus() == 1) {
                sellingWalletVo.setSellerStatus(SellerWallterStatus.CANCEL.getCode());
                sellingWalletVo.setStatusText(SellerWallterStatus.CANCEL.getText());
                sellingWalletVo.setIsShow(true);
            } else {
                if (sellingWalletVo.getWaiting() == SellerWallterStatus.POST.getCode()) {
                    sellingWalletVo.setSellerStatus(SellerWallterStatus.POST.getCode());
                    sellingWalletVo.setStatusText(SellerWallterStatus.POST.getText());
                    sellingWalletVo.setIsShow(false);
                }
                if (sellingWalletVo.getWaiting() == SellerWallterStatus.NO_POST.getCode()) {
                    sellingWalletVo.setSellerStatus(SellerWallterStatus.NO_POST.getCode());
                    sellingWalletVo.setStatusText(SellerWallterStatus.NO_POST.getText());
                    sellingWalletVo.setIsShow(false);
                }
            }
        }
        sellingWalletPagVo.setPageNum(pageNo);
        sellingWalletPagVo.setPageSize(pageSize);
        sellingWalletPagVo.setSellingWaters(data);
        sellingWalletPagVo.setTotalCount(pageDataVO.getTotalCount().intValue());
        sellingWalletPagVo.setTotalPage(pageDataVO.getTotalPage());
        return sellingWalletPagVo;
    }

    public List<Integer> findMemberIdByLeaderIdAndOrdreType(Integer leaderId, int orderType) {
        Example example = new Example(AppUserSellingWater.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userId", leaderId);
        criteria.andEqualTo("orderType", orderType);
        List<AppUserSellingWater> appUserSellingWaters = mapper.selectByExample(example);
        if (CollectionUtils.isEmpty(appUserSellingWaters)) {
            return Collections.EMPTY_LIST;
        }
        return appUserSellingWaters.stream().map(AppUserSellingWater::getSourceId).collect(Collectors.toList());
    }

    public PageDataVO<UserSellingWaterAdminDTO> findSellingWaterWithPage(UserSellingWaterFindDTO userSellingWaterFindDTO) {
        PageDataVO<UserSellingWaterAdminDTO> pageDataVO = PageDataVO.pageInfo(userSellingWaterFindDTO.getPage(),
                userSellingWaterFindDTO.getLimit(),
                () -> mapper.selectSellingWaterPage(userSellingWaterFindDTO));
        return pageDataVO;
    }

    public List<AppUserSellingWaterDTO> findStatffSellerWaterByUserIdsAndTime(List<Integer> userIds, Date startDate, Date endDate) {
 /*       List<UserStaffBo> userStaffBos = mapper.statisticsStatffSellerWaterByUserIdsAndTime(userIds,startDate.getTime(),endDate.getTime());
        return CollectionUtils.isEmpty(userStaffBos)?Collections.EMPTY_LIST:userStaffBos;*/
        List<AppUserSellingWaterDTO> appUserSellingWaterDTOS = new ArrayList<>();
        Example example = new Example(AppUserSellingWater.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("userId", userIds);
        if(startDate!=null && endDate!=null){
            criteria.andBetween("crtTime", startDate.getTime(), endDate.getTime());
        }
        if (startDate!=null && endDate==null){
            criteria.andGreaterThanOrEqualTo("crtTime",startDate.getTime());
        }

        if(startDate==null && endDate!=null){
            criteria.andLessThanOrEqualTo("crtTime",endDate.getTime());
        }
        criteria.andNotEqualTo("positionId", 6);
        List<AppUserSellingWater> appUserSellingWaters = mapper.selectByExample(example);
        if (CollectionUtils.isEmpty(appUserSellingWaters)) {
            return appUserSellingWaterDTOS;
        }
        AppUserSellingWaterDTO appUserSellingWaterDTO = null;
        for (AppUserSellingWater appUserSellingWater : appUserSellingWaters) {
            appUserSellingWaterDTO = new AppUserSellingWaterDTO();
            BeanUtils.copyProperties(appUserSellingWater, appUserSellingWaterDTO);
            appUserSellingWaterDTOS.add(appUserSellingWaterDTO);
        }
        return appUserSellingWaterDTOS;
    }

    private enum SellerWallterStatus {
        CANCEL(2, "取消订单"),
        POST(1, "已入账"),
        NO_POST(0, "未入账");
        private int code;
        private String text;

        SellerWallterStatus(int code, String text) {
            this.code = code;
            this.text = text;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }
    }

}