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

import com.github.wxiaoqi.security.admin.bo.UserIncomeBo;
import com.github.wxiaoqi.security.admin.dto.*;
import com.github.wxiaoqi.security.admin.entity.*;
import com.github.wxiaoqi.security.admin.mapper.AppUserSellingWaterMapper;
import com.github.wxiaoqi.security.admin.vo.SellingWalletPagVo;
import com.github.wxiaoqi.security.admin.vo.SellingWalletVo;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
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 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;

    @Autowired
    BaseOrderAcceptDetailedBiz acceptDetailedBiz;


    //计算用户拥金
    @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) {
        Integer acceptId = orderWaterDTO.getAcceptId() == null ? 0 :orderWaterDTO.getAcceptId();
        log.info("---分账id===="+acceptId);
        if (acceptId == 0 ){
            return;
        }
        BaseOrderAcceptDetailed acceptDetailed = acceptDetailedBiz.selectById(acceptId);
        if (acceptDetailed == null || (acceptDetailed.getDivisionType() != 2 && acceptDetailed.getDivisionType() != 4) ){
            return;
        }
        List<OrderGoodsDTO> goodsDTOList = orderWaterDTO.getGoodsDTOList();
        AppUserSellingWater sellingWater=new AppUserSellingWater();
        //订单id
        Integer orderId = orderWaterDTO.getOrderId();
        //订单号
        String orderNo = orderWaterDTO.getOrderNo();
        //用户id
        Integer userId = orderWaterDTO.getUserId();
        String goodId = null;
        Integer orderType = 0;
        String title=null;
        String img=null;
        Integer goodsNumber=0;
        if (goodsDTOList.size() > 0){
            OrderGoodsDTO goodsDto=goodsDTOList.get(0);
            goodId=goodsDto.getGoodId();
            orderType = goodsDto.getType();
            title=goodsDto.getTitle();
            img=goodsDto.getImg();
            goodsNumber=goodsDto.getGoodNumber();

        }
        sellingWater.setUserId(acceptDetailed.getMchId());
        sellingWater.setSourceId(userId);
        sellingWater.setOrderId(orderId);
        sellingWater.setOrderNo(orderNo);
        sellingWater.setOrderType(orderType);
        sellingWater.setGoodId(goodId);
        sellingWater.setTitle(title);
        sellingWater.setImg(img);
        sellingWater.setAcceptId(acceptId);
        sellingWater.setPrice(acceptDetailed.getOrderAmount());
        sellingWater.setExtract(acceptDetailed.getExtract());
        sellingWater.setGoodNumber(goodsNumber);
        sellingWater.setCommission(acceptDetailed.getDivisionAmount());
        insertSelective(sellingWater);
        log.info("购买计算用户未入账----payOrderWater--------userId===" + acceptDetailed.getMchId() + "----amount====" + acceptDetailed.getDivisionAmount() + "--orderType===" + orderType);
        if (orderType == 3) {
            finishOrderWater(orderWaterDTO);
        } else if (orderType == 1 || orderType == 2) {
            myWaterBiz.updMyWalletUnbooked(acceptDetailed.getMchId(), acceptDetailed.getDivisionAmount(), 1);
        }
    }

    //订单完成计算用户拥金
    public BigDecimal finishOrderWater(OrderWaterDTO orderWaterDTO) {
        AppUserSellingWater sellingWater=new AppUserSellingWater();
        sellingWater.setAcceptId(orderWaterDTO.getAcceptId());
        sellingWater.setWaiting(0);
        sellingWater =selectOne(sellingWater);
        if (sellingWater != null ){
            sellingWater.setWaiting(1);
            updateSelectiveById(sellingWater);
            return  sellingWater.getCommission();
        }
        return  BigDecimal.ZERO;
    }

    //订单完成计算用户拥金
    public void finishOrderFWater(OrderWaterDTO orderWaterDTO) {
        Integer acceptId = orderWaterDTO.getAcceptId() == null ? 0 :orderWaterDTO.getAcceptId();
        Integer zAcceptId = orderWaterDTO.getZAcceptId()== null ? 0 :orderWaterDTO.getZAcceptId();
        BigDecimal orderAmount = orderWaterDTO.getOrderAmount() == null ? BigDecimal.ZERO : orderWaterDTO.getOrderAmount();
        log.info("---分账id===="+acceptId+"----zAcceptId=="+zAcceptId+"---orderAmount===="+orderAmount);
        if (acceptId == 0 || zAcceptId == 0 || orderAmount.compareTo(BigDecimal.ZERO) == 0){
            return;
        }
        BaseOrderAcceptDetailed acceptDetailed = acceptDetailedBiz.selectById(acceptId);
        if (acceptDetailed == null || (acceptDetailed.getDivisionType() != 2 && acceptDetailed.getDivisionType() != 4) ){
            return;
        }
        AppUserSellingWater sellingWater =new AppUserSellingWater();
        sellingWater.setAcceptId(zAcceptId);
        sellingWater=selectOne(sellingWater);
        if (sellingWater != null ){
            sellingWater.setWaiting(1);
            updateSelectiveById(sellingWater);
            BigDecimal commission=orderAmount.multiply(sellingWater.getExtract()).divide(new BigDecimal(100)).setScale(2,   BigDecimal.ROUND_HALF_UP);
            sellingWater.setAcceptId(acceptId);
            sellingWater.setWaiting(1);
            sellingWater.setStatus(1);
            sellingWater.setCommission(commission);
            sellingWater.setPrice(orderAmount);
            sellingWater.setId(null);
            insertSelective(sellingWater);
        }
    }

    //订单退款计算用户拥金
    public void refundOrderWater(OrderWaterDTO orderWaterDTO) {
        Integer orderId = orderWaterDTO.getOrderId() == null ? 0 : orderWaterDTO.getOrderId();
        log.info("订单完成计算用户拥金----refundOrderWater----orderId====" + orderId);
        if ( orderId == 0) {
            return;
        }
        List<AppUserSellingWater> list = getWaterList(orderId);
        if (list.size() > 0) {
            for (AppUserSellingWater sellingWater : list) {
                sellingWater.setWaiting(1);
                updateById(sellingWater);
                sellingWater.setId(null);
                sellingWater.setStatus(1);
                insertSelective(sellingWater);;
            }
        }
    }


    public void updWalletByOrderId(OrderWaterDTO orderWaterDTO){
        Integer orderId = orderWaterDTO.getOrderId() == null ? 0 : orderWaterDTO.getOrderId();
        log.info("订单完成计算用户拥金----refundOrderWater----orderId====" + orderId);
        if ( orderId == 0) {
            return;
        }
        List<AppUserSellingWater> list=mapper.getCommisionByOrder(orderId);
        if (list.size() > 0){
            for (AppUserSellingWater appUserSellingWater:list){
                Integer userId=appUserSellingWater.getUserId();
                BigDecimal price=appUserSellingWater.getPrice() == null ? BigDecimal.ZERO :appUserSellingWater.getPrice();
                BigDecimal commission=appUserSellingWater.getCommission() == null ? BigDecimal.ZERO :appUserSellingWater.getCommission();
                if (price.compareTo(BigDecimal.ZERO) > 0){
                    myWaterBiz.updMyWalletUnbooked(userId,price,2);
                }
                if (commission.compareTo(BigDecimal.ZERO) > 0){
                    MyWalletDetail detail=new MyWalletDetail();
                    detail.setUserId(userId);
                    detail.setAmount(commission);
                    detail.setCono(orderId);
                    detail.setWithDrawOrderNo(appUserSellingWater.getOrderNo());
                    detail.setSource(1);
                    myWaterBiz.updMyWater(detail);
                }
            }
        }
    }


    //获取拥金列表
    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())==null?"":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;
        }
    }

}