package com.zhongzheng.modules.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zhongzheng.common.exception.CustomException;
import com.zhongzheng.common.utils.DateUtils;
import com.zhongzheng.modules.activity.domain.ActivityConfiguration;
import com.zhongzheng.modules.activity.service.IActivityConfigurationService;
import com.zhongzheng.modules.activity.service.IActivityConfigurationUseService;
import com.zhongzheng.modules.activity.vo.ActivityConfigurationVo;
import com.zhongzheng.modules.bank.service.IQuestionBankService;
import com.zhongzheng.modules.bank.vo.QuestionBankVo;
import com.zhongzheng.modules.bank.vo.QuestionVo;
import com.zhongzheng.modules.collect.bo.CollectBankQueryBo;
import com.zhongzheng.modules.collect.bo.CollectCourseQueryBo;
import com.zhongzheng.modules.collect.domain.CollectBank;
import com.zhongzheng.modules.collect.service.ICollectBankService;
import com.zhongzheng.modules.collect.service.ICollectCourseService;
import com.zhongzheng.modules.collect.vo.CollectBankVo;
import com.zhongzheng.modules.collect.vo.CollectCourseVo;
import com.zhongzheng.modules.course.domain.Course;
import com.zhongzheng.modules.course.service.ICourseService;
import com.zhongzheng.modules.course.vo.CourseVo;
import com.zhongzheng.modules.exam.service.IExamNoteService;
import com.zhongzheng.modules.exam.vo.ExamNoteVo;
import com.zhongzheng.modules.order.bo.*;
import com.zhongzheng.modules.order.domain.Coupon;
import com.zhongzheng.modules.order.domain.Order;
import com.zhongzheng.modules.order.domain.OrderActivity;
import com.zhongzheng.modules.order.domain.OrderCoupon;
import com.zhongzheng.modules.order.mapper.OrderMapper;
import com.zhongzheng.modules.order.service.*;
import com.zhongzheng.modules.order.vo.CouponVo;
import com.zhongzheng.modules.order.vo.OrderGoodsVo;
import com.zhongzheng.modules.order.vo.OrderVo;
import com.zhongzheng.modules.order.vo.UserOrderInFo;
import com.zhongzheng.modules.user.bo.OrderPossessUserAddBo;
import com.zhongzheng.modules.user.bo.OrderPossessUserQueryBo;
import com.zhongzheng.modules.user.bo.RanKingUserQuery;
import com.zhongzheng.modules.user.domain.OrderPossessUser;
import com.zhongzheng.modules.user.domain.User;
import com.zhongzheng.modules.user.mapper.UserMapper;
import com.zhongzheng.modules.user.service.IOrderPossessUserService;
import com.zhongzheng.modules.user.service.IUserBankQuestionRecordService;
import com.zhongzheng.modules.user.service.IUserService;
import com.zhongzheng.modules.user.vo.OrderPossessUserVo;
import com.zhongzheng.modules.user.vo.RanKingUser;
import com.zhongzheng.modules.user.vo.UserVo;
import com.zhongzheng.modules.wx.service.IWxPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author hjl
 * @date 2021-05-19
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private IWxPayService iWxPayService;

    @Autowired
    private IUserService iUserService;

    @Autowired
    private IOrderGoodsService iOrderGoodsService;

    @Autowired
    private ICourseService iCourseService;

    @Autowired
    private IQuestionBankService iQuestionBankService;

    @Autowired
    private IExamNoteService iExamNoteService;

    @Autowired
    private IOrderPossessUserService iOrderPossessUserService;

    @Autowired
    private ICouponService iCouponService;

    @Autowired
    private IOrderCouponService iOrderCouponService;

    @Autowired
    private IActivityConfigurationService activityConfigurationService;

    @Autowired
    private IActivityConfigurationUseService activityConfigurationUseService;


    @Autowired
    private IOrderActivityService oOrderActivityService;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ICollectBankService iCollectBankService;

    @Autowired
    private ICollectCourseService iCollectCourseService;

    @Override
    public OrderVo queryById(Long orderId){
        Order db = this.baseMapper.selectById(orderId);
        return BeanUtil.toBean(db, OrderVo.class);
    }

    @Override
    public Order queryByOrderSn(String orderSn) {
        Order info = getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOderSn,orderSn)
                .last("limit 1"));
        return info;
    }

    @Override
    public List<OrderVo> queryList(OrderQueryBo bo) {
        LambdaQueryWrapper<Order> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getOderSn()), Order::getOderSn, bo.getOderSn());
        lqw.eq(bo.getUserId() != null, Order::getUserId, bo.getUserId());
        lqw.eq(bo.getOrderPrice() != null, Order::getOrderPrice, bo.getOrderPrice());
        lqw.eq(StrUtil.isNotBlank(bo.getOrderGeneral()), Order::getOrderGeneral, bo.getOrderGeneral());
        lqw.eq(bo.getOrderStatus() != null, Order::getOrderStatus, bo.getOrderStatus());
        lqw.eq(bo.getPayTime() != null, Order::getPayTime, bo.getPayTime());
        lqw.eq(bo.getPayType() != null, Order::getPayType, bo.getPayType());
        lqw.eq(StrUtil.isNotBlank(bo.getTransid()), Order::getTransid, bo.getTransid());
        lqw.eq(bo.getCancelTime() != null, Order::getCancelTime, bo.getCancelTime());
        lqw.eq(bo.getFinishTime() != null, Order::getFinishTime, bo.getFinishTime());
        return entity2Vo(this.list(lqw));
    }

    @Override
    public List<Order> getOrderGoodsList(OrderQueryBo bo) {
        return orderMapper.getOrderGoodsList(bo);
    }

    /**
    * 实体类转化成视图对象
    *
    * @param collection 实体类集合
    * @return
    */
    private List<OrderVo> entity2Vo(Collection<Order> collection) {
        List<OrderVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, OrderVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<Order> page = (Page<Order>)collection;
            Page<OrderVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page,pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Override
    public Boolean insertByAddBo(OrderAddBo bo) {
        Order add = BeanUtil.toBean(bo, Order.class);
        validEntityBeforeSave(add);
        add.setCreateTime(DateUtils.getNowTime());
        add.setUpdateTime(DateUtils.getNowTime());
        return this.save(add);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> placeOrder(OrderAddBo bo) {
        List<OrderGoodsAddBo> goodsList = bo.getGoodsList();
        if(goodsList.size()<1){
            throw new CustomException("商品列表为空");
        }
        Order add = BeanUtil.toBean(bo, Order.class);
        validEntityBeforeSave(add);
        add.setCreateTime(DateUtils.getNowTime());
        add.setUpdateTime(DateUtils.getNowTime());
        Map<String, String> result = dealOrder(add,goodsList,bo.getCouponId(),bo.getActivityId());

        return result;
    }

    @Override
    public Map<String, String> placeGzhCoinOrder(OrderAddBo bo) {
        List<OrderGoodsAddBo> goodsList = bo.getGoodsList();
        if(goodsList.size()<1){
            throw new CustomException("商品列表为空");
        }
        Order add = BeanUtil.toBean(bo, Order.class);
        validEntityBeforeSave(add);
        add.setCreateTime(DateUtils.getNowTime());
        add.setUpdateTime(DateUtils.getNowTime());
        Map<String, String> result = dealGzhOrder(add,goodsList,bo.getUrl());
        return result;
    }

    @Override
    public Map<String, String> placeSmallCoinOrder(OrderAddBo bo) {
        List<OrderGoodsAddBo> goodsList = bo.getGoodsList();
        if(goodsList.size()<1){
            throw new CustomException("商品列表为空");
        }
        Order add = BeanUtil.toBean(bo, Order.class);
        validEntityBeforeSave(add);
        add.setCreateTime(DateUtils.getNowTime());
        add.setUpdateTime(DateUtils.getNowTime());
        Map<String, String> result = dealSmallCoinOrder(add,goodsList,bo.getUrl());
        return result;
    }

    @Override
    public Boolean updateByEditBo(OrderEditBo bo) {
        Order update = BeanUtil.toBean(bo, Order.class);
        validEntityBeforeSave(update);
        return this.updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Order entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return this.removeByIds(ids);
    }

    @Override
    public UserOrderInFo listUserOrder(OrderQueryBo bo) {
        if (bo.getUserId() == null){
            throw new IllegalArgumentException("用户ID为空");
        }
        LambdaQueryWrapper<Order> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, Order::getUserId, bo.getUserId());
        lqw.eq(Order::getOrderStatus, 1);
        List<Order> list = this.list(lqw);
        BigDecimal price = new BigDecimal("0");
        if(!CollectionUtils.isEmpty(list)) {

            for (Order order : list) {
                price = price.add(order.getOrderPrice());
            }
        }
        List<CouponVo> couponVos=iCouponService.listUserOrder(bo.getUserId(),0);
        List<CouponVo> couponDiscounts=iCouponService.listUserOrder(bo.getUserId(),1);
        UserVo userVo = iUserService.queryById(bo.getUserId());
        Integer count = activityConfigurationUseService.queryByCount(bo.getUserId());
        RanKingUserQuery ranKingUserQuery = new RanKingUserQuery();
        ranKingUserQuery.setUserId(bo.getUserId());
        RanKingUser ranKingUser = userMapper.selectByRank(ranKingUserQuery);
        OrderPossessUserQueryBo orderPossessUserQueryBo = new OrderPossessUserQueryBo();
        orderPossessUserQueryBo.setUserId(bo.getUserId());
        orderPossessUserQueryBo.setTypeId(1);
        OrderPossessUserVo cousreList = iOrderPossessUserService.queryList(orderPossessUserQueryBo);
        orderPossessUserQueryBo.setTypeId(2);
        OrderPossessUserVo bankList = iOrderPossessUserService.queryList(orderPossessUserQueryBo);
        CollectBankQueryBo collectBankQueryBo = new CollectBankQueryBo();
        collectBankQueryBo.setUserId(bo.getUserId());
        List<CollectBankVo> collectList = iCollectBankService.selectList(collectBankQueryBo);
        CollectCourseQueryBo collectCourseQueryBo = new CollectCourseQueryBo();
        collectCourseQueryBo.setUserId(bo.getUserId());
        List<CollectCourseVo> collectCourseList = iCollectCourseService.selectList(collectCourseQueryBo);
        UserOrderInFo userOrderInFo = new UserOrderInFo();
        userOrderInFo.setPrice(price);
        userOrderInFo.setOrderNum(list.size());
        userOrderInFo.setCouponDiscount(couponDiscounts.size());
        userOrderInFo.setCoupon(couponVos.size());
        userOrderInFo.setUserLevel(userVo.getUserLevel());
        userOrderInFo.setIntegral(userVo.getIntegral());
        userOrderInFo.setActivityNum(count);
        userOrderInFo.setStudyNum(getHour(ranKingUser.getHourse()));
        userOrderInFo.setCourseNum(cousreList.getCourseVoList().size());
        userOrderInFo.setBankNum(bankList.getQuestionBankList().size());
        userOrderInFo.setCollectCourseNum(collectCourseList.size());
        userOrderInFo.setCollectBankNum(collectList.size());
        return userOrderInFo;
    }

    //Util.java
    public static String getHour(String date) {
        //秒数
        Integer dt = Integer.parseInt(date) ;
        if (dt < 3600) return Math.round(dt / 60) + "m";
        int hour = Math.round(dt / 3600);
        int minute = Math.round((dt - (hour * 3600)) / 60);
        return hour + "h" + (minute == 0 ? "" : minute + "m");
    }

    //购买课程题库重点
    public Map<String, String>  dealOrder(Order add,List<OrderGoodsAddBo> goodsList,Long couponId,Long activity){
        UserVo userVo = iUserService.queryById(add.getUserId());
        String body = "中正云课堂消费";
        String price = "1";
        String out_trade_no = DateUtils.getDateOrderSn();
        add.setOderSn(out_trade_no);
        add.setPayType(3); //金币支付
        add.setOrderType(2);
        BigDecimal totalPrice = new BigDecimal(0);
        BigDecimal payPrice = new BigDecimal(0);
        Boolean couponBool = true;
        for (OrderGoodsAddBo g : goodsList) {
            g.setOrderSn(out_trade_no);
            if(g.getNum()<1){
                throw new CustomException("商品数量错误");
            }
            //课程
            if(g.getGoodsType()==1){
                CourseVo courseVo = iCourseService.queryById(g.getGoodsId());
                if(courseVo==null||courseVo.getStatus()!=1){
                    throw new CustomException("课程无法购买");
                }
                g.setGoodsPrice(courseVo.getPrice());
            }
            //题库
            if(g.getGoodsType()==2){
                QuestionBankVo questionBankVo = iQuestionBankService.queryById(g.getGoodsId());
                if(questionBankVo==null||questionBankVo.getStatus()!=1){
                    throw new CustomException("题库无法购买");
                }
                g.setGoodsPrice(questionBankVo.getPrice());
            }
            //考试重点
            if(g.getGoodsType()==3){
                ExamNoteVo examNoteVo = iExamNoteService.queryById(g.getGoodsId());
                if(examNoteVo==null||examNoteVo.getStatus()!=1){
                    throw new CustomException("考试重点无法购买");
                }
                g.setGoodsPrice(examNoteVo.getPrice());
            }
            OrderPossessUser orderPossess =iOrderPossessUserService.queryByTypeAndId(g.getGoodsId(),g.getGoodsType(),add.getUserId());
            if(Validator.isNotNull(orderPossess)){
                throw new CustomException("你已购买该商品");
            }
            if(!iOrderGoodsService.insertByAddBo(g)){
                throw new CustomException("商品错误");
            }
            //查詢該券是否使用於此課程上
            if(couponBool && couponId!=null&&couponId>0 && g.getGoodsType()==1 && iCouponService.selectCount(g.getGoodsId(),couponId) > 0 ){
                //使用优惠券
                Coupon coupon= iCouponService.queryByIdAndUserId(couponId,add.getUserId());
                if(!Validator.isNotNull(coupon)){
                    throw new CustomException("该优惠券不存在");
                }
                if(coupon.getUserStatus()!=0||coupon.getEndTime()<DateUtils.getNowTime()){
                    throw new CustomException("该优惠券无法使用");
                }
                if(coupon.getCouponType()==0){
                    //优惠券
                    g.setGoodsPrice(g.getGoodsPrice().subtract(coupon.getPrice()));

                }
                if(coupon.getCouponType()==1){
                    //折扣券
                    g.setGoodsPrice(g.getGoodsPrice().divide((new BigDecimal(10))).multiply(coupon.getPrice()));
                }
                OrderCouponAddBo orderCouponAddBo = new OrderCouponAddBo();
                orderCouponAddBo.setCouponId(couponId);
                orderCouponAddBo.setOrderSn(out_trade_no);
                couponBool=false;
                if(!iOrderCouponService.insertByAddBo(orderCouponAddBo)){
                    throw new CustomException("优惠券数据错误");
                }
            }
            //订单价格不计算优惠
            totalPrice = totalPrice.add(g.getGoodsPrice());
            //查詢該活動是否使用於此課程上
            if(activity!=null&&activity >0 && g.getGoodsType()==1 && activityConfigurationService.selectCount(g.getGoodsId(),activity) > 0 ){
                //使用活動
                ActivityConfigurationVo activityConfigurationVo = activityConfigurationService.queryById(activity);
                if(!Validator.isNotNull(activityConfigurationVo)){
                    throw new CustomException("该活動不存在");
                }
                if(Convert.toLong(activityConfigurationVo.getActivityType()) ==3){
                    //定價
                    g.setGoodsPrice(activityConfigurationVo.getPrice());
                }
                if(Convert.toLong(activityConfigurationVo.getActivityType()) ==4){
                    //優惠
                    g.setGoodsPrice(g.getGoodsPrice().subtract((activityConfigurationVo.getPrice())));
                }
                if(Convert.toLong(activityConfigurationVo.getActivityType()) ==5){
                    //折扣
                    g.setGoodsPrice(g.getGoodsPrice().divide((new BigDecimal(10))).multiply(activityConfigurationVo.getPrice()));
                }
                OrderActivityAddBo orderActivityAddBo = new OrderActivityAddBo();
                orderActivityAddBo.setActivityId(activity);
                orderActivityAddBo.setOrderSn(out_trade_no);
                if(!oOrderActivityService.insertByAddBo(orderActivityAddBo)){
                    throw new CustomException("活動錯誤");
                }
            }

            payPrice = payPrice.add(g.getGoodsPrice());

        }
        BigDecimal zero = new BigDecimal("0.01");
        if(totalPrice.compareTo(zero) < 0){
            //价格不能小于0.01
            totalPrice = zero;
        }
        add.setOrderPrice(totalPrice);

        if(payPrice.compareTo(zero) < 0){
            //价格不能小于0.01
            payPrice = zero;
        }
        add.setPayPrice(payPrice);

        if(userVo.getMoney().compareTo(payPrice) < 0){
            throw new CustomException("金币不足");
        }
        userVo.setMoney(userVo.getMoney().subtract(payPrice));
        add.setOrderStatus(0);
        if(!this.save(add)){
            throw new CustomException("订单数据错误");
        }
        dealCoinOrder(add.getOderSn());
    //    Map<String, String> result =  iWxPayService.payment(out_trade_no,userVo.getOpenId(),body,price);
        return null;
    }

    //金币支付
    public Boolean dealCoinOrder(String out_trade_no){
        Order order = queryByOrderSn(out_trade_no);
        if(order.getOrderStatus()==0){
            order.setOrderStatus(1);
            order.setPayTime(DateUtils.getNowTime());
            order.setOrderGeneral(out_trade_no);
            if(updateById(order)){
                OrderGoodsQueryBo bo = new OrderGoodsQueryBo();
                bo.setOrderSn(out_trade_no);
                List<OrderGoodsVo> goodsList = iOrderGoodsService.queryList(bo);
                for (OrderGoodsVo g : goodsList) {
                    //扣除金币
                    UpdateWrapper<User> updateUserWrapper = new UpdateWrapper<>();
                    updateUserWrapper.setSql("money = money -"+g.getGoodsPrice());
                    updateUserWrapper.eq("user_id", order.getUserId());
                    iUserService.update(updateUserWrapper);
                    //添加入我的学习
                    OrderPossessUserAddBo addBo = new OrderPossessUserAddBo();
                    addBo.setUserId(order.getUserId());
                    addBo.setPossessId(g.getGoodsId());
                    addBo.setTypeId(g.getGoodsType());
                    addBo.setSourceId(0);//订单来源
                    iOrderPossessUserService.insertByAddBo(addBo);
                }
                //用优惠券更新状态
                OrderCoupon orderCoupon = iOrderCouponService.queryBySn(out_trade_no);
                if(Validator.isNotNull(orderCoupon)){
                    UpdateWrapper<Course> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.setSql("user_status = "+1);
                    updateWrapper.eq("coupon_id", orderCoupon.getCouponId());
                    iCourseService.update(updateWrapper);
                }
                return true;
            }
        }
        return false;
    }

    public Map<String, String>  dealGzhOrder(Order add,List<OrderGoodsAddBo> goodsList,String url){
        UserVo userVo = iUserService.queryById(add.getUserId());
        String body = "中正云课堂充值";
        String price = "1";
        String out_trade_no = DateUtils.getDateOrderSn();
        add.setOderSn(out_trade_no);
        add.setPayType(1); //微信支付
        add.setOrderStatus(0);
        add.setOrderType(1);
        BigDecimal totalPrice = new BigDecimal(0);
        for (OrderGoodsAddBo g : goodsList) {
            g.setOrderSn(out_trade_no);
            if(g.getNum()<1){
                throw new CustomException("商品数量错误");
            }
            g.setGoodsType(4);//充值余额类型
            g.setGoodsId(0L);
            if(!iOrderGoodsService.insertByAddBo(g)){
                throw new CustomException("商品错误");
            }
            totalPrice = totalPrice.add(g.getGoodsPrice());
        }
        BigDecimal zero = new BigDecimal("0.01");
        if(totalPrice.compareTo(zero) < 0){
            //价格不能小于0.01
            totalPrice = zero;
        }

        add.setOrderPrice(totalPrice);
        if(!this.save(add)){
            throw new CustomException("订单数据错误");
        }
        Map<String, String> result =  iWxPayService.paymentGzh(out_trade_no,userVo.getGzhOpenId(),body,totalPrice,url);
        return result;
    }

    //小程序金币购买
    public Map<String, String>  dealSmallCoinOrder(Order add,List<OrderGoodsAddBo> goodsList,String url){
        UserVo userVo = iUserService.queryById(add.getUserId());
        String body = "中正云课堂充值";
        String price = "1";
        String out_trade_no = DateUtils.getDateOrderSn();
        add.setOderSn(out_trade_no);
        add.setPayType(1); //微信支付
        add.setOrderStatus(0);
        add.setOrderType(1);
        BigDecimal totalPrice = new BigDecimal(0);
        for (OrderGoodsAddBo g : goodsList) {
            g.setOrderSn(out_trade_no);
            if(g.getNum()<1){
                throw new CustomException("商品数量错误");
            }
            g.setGoodsType(4);//充值余额类型
            g.setGoodsId(0L);
            if(!iOrderGoodsService.insertByAddBo(g)){
                throw new CustomException("商品错误");
            }
            totalPrice = totalPrice.add(g.getGoodsPrice());
        }
        BigDecimal zero = new BigDecimal("0.01");
        if(totalPrice.compareTo(zero) < 0){
            //价格不能小于0.01
            totalPrice = zero;
        }

        add.setOrderPrice(totalPrice);
        add.setPayPrice(totalPrice);
        if(!this.save(add)){
            throw new CustomException("订单数据错误");
        }
        Map<String, String> result =  iWxPayService.payment(out_trade_no,userVo.getOpenId(),body,price);
        return result;
    }

}
