package com.cyl.manager.oms.service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cyl.manager.act.domain.entity.IntegralHistory;
import com.cyl.manager.act.mapper.IntegralHistoryMapper;
import com.cyl.manager.act.service.MemberCouponService;
import com.cyl.manager.oms.convert.OrderOperateHistoryConvert;
import com.cyl.manager.oms.domain.entity.*;
import com.cyl.manager.oms.mapper.*;
import com.cyl.manager.oms.domain.form.DealWithAftersaleForm;
import com.cyl.manager.oms.domain.form.ManagerAftersaleOrderForm;
import com.cyl.manager.oms.domain.vo.*;
import com.cyl.manager.pms.mapper.SkuMapper;
import com.cyl.manager.ums.domain.entity.Member;
import com.cyl.manager.ums.domain.entity.MemberWechat;
import com.cyl.manager.ums.mapper.MemberMapper;
import com.cyl.manager.ums.mapper.MemberWechatMapper;
import com.cyl.wechat.WechatPayService;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.AftersaleStatus;
import com.ruoyi.common.enums.OrderRefundStatus;
import com.ruoyi.common.enums.OrderStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.framework.config.LocalDataUtil;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 订单售后Service业务层处理
 *
 * @author zcc
 */
@Service
@Slf4j
public class AftersaleService {
    @Autowired
    private AftersaleMapper aftersaleMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private OrderOperateHistoryMapper orderOperateHistoryMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private OrderOperateHistoryConvert historyConvert;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private MemberCouponService memberCouponService;
    @Autowired
    private WechatPaymentHistoryMapper wechatPaymentHistoryMapper;
    @Autowired
    private MemberWechatMapper memberWechatMapper;
    @Autowired(required = false)
    private WechatPayService wechatPayService;
    @Autowired
    private OrderOperateHistoryMapper operateHistoryMapper;
    @Autowired
    private IntegralHistoryMapper integralHistoryMapper;

    /**
     * 查询订单售后
     *
     * @param id 订单售后主键
     * @return 订单售后
     */
    public ManagerRefundOrderDetailVO selectById(Long id) {
        Order order = orderMapper.selectById(id);
        if (order == null) {
            throw new RuntimeException("无该订单信息");
        }
        ManagerRefundOrderDetailVO result = new ManagerRefundOrderDetailVO();
        //订单基本信息
        result.setOrderId(order.getId());
        result.setOrderSn(order.getOrderSn());
        result.setCreateTime(order.getCreateTime());
        result.setPayType(order.getPayType());
        result.setPayTime(order.getPaymentTime());
        result.setStatus(order.getStatus());
        result.setExpressName(order.getDeliveryCompany());
        result.setDeliveryTime(order.getDeliveryTime());
        result.setExpressNo(order.getDeliverySn());
        result.setTotalAmount(order.getTotalAmount());
        result.setPayAmount(order.getPayAmount());
        //用户信息
        Member member = memberMapper.selectById(order.getMemberId());
        result.setNickName(member.getNickname());
        result.setPhone(member.getPhoneHidden());
        //收货信息
        OrderAddressVO orderAddressVO = new OrderAddressVO();
        orderAddressVO.setAddress(order.getReceiverDetailAddress());
        orderAddressVO.setName(order.getReceiverName());
        orderAddressVO.setUserPhone(order.getReceiverPhone());
        orderAddressVO.setArea(order.getReceiverProvince() + order.getReceiverCity() + order.getReceiverDistrict());
        result.setAddressInfo(orderAddressVO);
        //orderItem
        QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
        orderItemQw.eq("order_id", id);
        List<OrderItem> orderItemList = orderItemMapper.selectList(orderItemQw);
        List<ManagerOrderProductVO> productList = new ArrayList<>();
        orderItemList.forEach(orderItem -> {
            ManagerOrderProductVO productVO = new ManagerOrderProductVO();
            productVO.setPic(orderItem.getPic());
            productVO.setSpData(orderItem.getSpData());
            productVO.setProductName(orderItem.getProductName());
            productVO.setSalePrice(orderItem.getSalePrice());
            productVO.setBuyNum(orderItem.getQuantity());
            productVO.setProductId(orderItem.getProductId());
            productList.add(productVO);
        });
        result.setProductList(productList);
        //售后信息
        QueryWrapper<Aftersale> aftersaleQw = new QueryWrapper<>();
        aftersaleQw.eq("order_id", order.getId());
        aftersaleQw.orderByDesc("create_time");
        List<Aftersale> aftersaleList = aftersaleMapper.selectList(aftersaleQw);
        List<RefundInfoVO> refundInfoList = new ArrayList<>();
        aftersaleList.forEach(aftersale -> {
            RefundInfoVO refundInfo = new RefundInfoVO();
            refundInfo.setId(aftersale.getId());
            refundInfo.setApplyRefundType(aftersale.getType());
            refundInfo.setApplyRefundTime(aftersale.getCreateTime());
            refundInfo.setRefundAmount(aftersale.getReturnAmount());
            refundInfo.setReason(aftersale.getReason());
            refundInfo.setDescription(aftersale.getDescription());
            refundInfo.setProofPics(aftersale.getProofPics());
            refundInfo.setRefundStatus(aftersale.getStatus());
            refundInfo.setRefundWpCode(aftersale.getRefundWpCode());
            refundInfo.setRefundWaybillCode(aftersale.getRefundWaybillCode());
            refundInfo.setRefundStatus(aftersale.getStatus());
            refundInfo.setRemark(aftersale.getHandleNote());
            refundInfoList.add(refundInfo);
        });
        result.setRefundInfoList(refundInfoList);
        return result;
    }

    /**
     * 查询订单售后列表
     *
     * @param query 查询条件
     * @param page  分页条件
     * @return 订单售后
     */
    public List<ManagerRefundOrderVO> selectList(ManagerAftersaleOrderForm query, Pageable page) {
        if (page != null) {
            PageHelper.startPage(page.getPageNumber() + 1, page.getPageSize());
        }
        if (StrUtil.isNotBlank(query.getOrderSn()) && query.getOrderSn().length() > 7) {
            query.setOrderSn(query.getOrderSn().substring(7));
        }
        List<ManagerRefundOrderVO> managerRefundOrderVOS = aftersaleMapper.selectManagerRefundOrder(query);
        if (CollectionUtil.isEmpty(managerRefundOrderVOS)) {
            return managerRefundOrderVOS;
        }
        Set<Long> idSet = managerRefundOrderVOS.stream().map(ManagerRefundOrderVO::getOrderId).collect(Collectors.toSet());
        //查一下orderSn集合
        QueryWrapper<Order> orderQw = new QueryWrapper<>();
        orderQw.in("id", idSet);
        Map<Long, Order> orderMap = orderMapper.selectList(orderQw).stream().collect(Collectors.toMap(Order::getId, it -> it));
        //封装售后单商品数据
        QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
        orderItemQw.in("order_id", idSet);
        Map<Long, List<OrderItem>> orderItemMap = orderItemMapper.selectList(orderItemQw).stream().collect(Collectors.groupingBy(OrderItem::getOrderId));
        managerRefundOrderVOS.forEach(vo -> {
            Order order = orderMap.get(vo.getOrderId());
            vo.setOrderSn(order.getOrderSn());
            List<OrderItem> orderItemList = orderItemMap.get(vo.getOrderId());
            List<ManagerOrderProductVO> productList = new ArrayList<>();
            orderItemList.forEach(item -> {
                ManagerOrderProductVO productVO = new ManagerOrderProductVO();
                productVO.setProductName(item.getProductName());
                productVO.setSalePrice(item.getSalePrice());
                productVO.setPic(item.getPic());
                productVO.setBuyNum(item.getQuantity());
                productVO.setProductId(item.getProductId());
                productVO.setSpData(item.getSpData());
                productList.add(productVO);
            });
            vo.setProductList(productList);
        });
        return managerRefundOrderVOS;
    }

    /**
     * 新增订单售后
     *
     * @param aftersale 订单售后
     * @return 结果
     */
    public int insert(Aftersale aftersale) {
        aftersale.setCreateTime(LocalDateTime.now());
        return aftersaleMapper.insert(aftersale);
    }

    /**
     * 修改订单售后
     *
     * @param aftersale 订单售后
     * @return 结果
     */
    public int update(Aftersale aftersale) {
        return aftersaleMapper.updateById(aftersale);
    }

    /**
     * 删除订单售后信息
     *
     * @param id 订单售后主键
     * @return 结果
     */
    public int deleteById(Long id) {
        return aftersaleMapper.deleteById(id);
    }

    /**
     * 售后处理
     *
     * @param request 请求体
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void dealWith(DealWithAftersaleForm request, Long userId, String optUserName) {
        Order order = orderMapper.selectById(request.getOrderId());
        if (order == null) {
            throw new RuntimeException("无该订单");
        }
        LocalDateTime optDate = LocalDateTime.now();
        //不是0元订单
        if (order.getPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            //只申请一笔售后
            if (request.getOrderItemId() != null) {
                List<OrderItem> orderItem = orderItemMapper.selectList(new QueryWrapper<OrderItem>().eq("id", request.getOrderItemId()));
                if (CollectionUtil.isNotEmpty(orderItem)) {
                    // 是否需要发起退款
                    if (request.getOptType() == Constants.OptType.AGREE) {
                        BigDecimal money = new BigDecimal("0.00");
                        if (orderItem.get(0).getCouponMoney() == null || orderItem.get(0).getCouponMoney().compareTo(BigDecimal.ZERO) <= 0) {
                            money = orderItem.get(0).getSalePrice();
                        } else {
                            money = orderItem.get(0).getCouponMoney();
                        }
                        BigDecimal multiply = money.multiply(BigDecimal.valueOf(orderItem.get(0).getQuantity()));
                        //开始退款
                        Refund wechatResponse = wechatPayService.refundPay(order.getOrderSn() + RandomUtil.randomNumbers(5),
                                order.getPayId() + "",
                                "https://wenchuang.yyinhong.cn/api/no-auth/wechat/weChatRefundNotify",
                                multiply.multiply(new BigDecimal("100")).longValue(),
                                order.getPayAmount().multiply(new BigDecimal("100")).longValue(), request.getReason());
                        log.info("发起微信退款返回信息,tradeRefund:{}", JSONObject.toJSONString(wechatResponse == null ? "" : wechatResponse));
                        //库存回滚
                        orderItem.stream().collect(Collectors.groupingBy(it -> it.getSkuId())).forEach((k, v) -> {
                            AtomicReference<Integer> totalCount = new AtomicReference<>(0);
                            v.forEach(it -> totalCount.updateAndGet(v1 -> v1 + it.getQuantity()));
                            skuMapper.updateStockById(k, optDate, -1 * totalCount.get());
                        });
                        //处理积分
                        sendBack(request.getMemberId(), null, orderItem.get(0).getId());
                    }
                }
                //全部退款
            } else {
                if (request.getOptType() == Constants.OptType.AGREE) {
                    //开始退款
                    Refund wechatResponse = wechatPayService.refundPay(order.getOrderSn() + RandomUtil.randomNumbers(5),
                            order.getPayId() + "",
                            "https://wenchuang.yyinhong.cn/api/no-auth/wechat/weChatRefundNotify",
                            order.getPayAmount().multiply(new BigDecimal("100")).longValue(),
                            order.getPayAmount().multiply(new BigDecimal("100")).longValue(),
                            request.getReason());
                    log.info("发起微信退款返回信息,tradeRefund:{}", JSONObject.toJSONString(wechatResponse == null ? "" : wechatResponse));
                    List<OrderItem> orderItem = orderItemMapper.selectList(new QueryWrapper<OrderItem>().eq("order_id", request.getOrderId()));
                    if (CollectionUtil.isNotEmpty(orderItem)) {
                        //库存回滚
                        orderItem.stream().collect(Collectors.groupingBy(it -> it.getSkuId())).forEach((k, v) -> {
                            AtomicReference<Integer> totalCount = new AtomicReference<>(0);
                            v.forEach(it -> totalCount.updateAndGet(v1 -> v1 + it.getQuantity()));
                            skuMapper.updateStockById(k, optDate, -1 * totalCount.get());
                        });
                    }
                    //处理积分
                    sendBack(request.getMemberId(), order.getId(), null);

                    //修改子订单状态
                    List<OrderItem> orderItems = orderItemMapper.selectList(new QueryWrapper<OrderItem>().eq("order_id", request.getOrderId()));
                    if (CollectionUtil.isNotEmpty(orderItems)) {
                        for (OrderItem item : orderItems) {
                            item.setStatus("9");
                            orderItemMapper.updateById(item);
                        }
                    }
                }
            }
        } else {
            //处理积分
            sendBack(request.getMemberId(), order.getId(),null);
        }
        //要创建的订单操作记录,status后续判断再设置
        OrderOperateHistory optHistory = new OrderOperateHistory();
        optHistory.setOrderId(order.getId());
        optHistory.setOrderSn(order.getOrderSn());
        optHistory.setOperateMan("后台管理员");
        optHistory.setCreateTime(optDate);
        optHistory.setCreateBy(userId);
        optHistory.setUpdateBy(userId);
        optHistory.setUpdateTime(optDate);
        //封装订单wrapper
        UpdateWrapper<Order> orderWrapper = new UpdateWrapper<>();
        orderWrapper.eq("id", request.getOrderId());
        orderWrapper.set("update_time", optDate);
        orderWrapper.set("update_by", userId);
        orderWrapper.set("reason", request.getReason());
        orderWrapper.set("proof_pics", request.getProofPics());
        orderWrapper.set("status", OrderStatus.CLOSED.getType());
        int row = orderMapper.update(null, orderWrapper);
        if (row != 1) {
            throw new RuntimeException("修改订单状态失败");
        }
        List<OrderItem> orderItem = orderItemMapper.selectList(new QueryWrapper<OrderItem>().eq("order_id", request.getOrderId()));
        //库存回滚
        orderItem.stream().collect(Collectors.groupingBy(it -> it.getSkuId())).forEach((k, v) -> {
            AtomicReference<Integer> totalCount = new AtomicReference<>(0);
            v.forEach(it -> totalCount.updateAndGet(v1 -> v1 + it.getQuantity()));
            skuMapper.updateStockById(k, optDate, -1 * totalCount.get());
        });
        optHistory.setOrderStatus(OrderStatus.CLOSED.getType());
        int his = orderOperateHistoryMapper.insert(optHistory);
        if (his != 1) {
            log.info("订单日志记录失败!");
        }
    }


    /**
     * 退回积分
     */
    public void sendBack(Long memberId, Long orderId, Long orderItemId) {
        BigDecimal integral = new BigDecimal("0.00");
        if (orderItemId != null) {
            //只返回一部分积分
            OrderItem orderItem = orderItemMapper.selectById(orderItemId);
            if (null == orderItem) {
                throw new ServiceException("退款商品信息有误!");
            } else {
                if (orderItem.getUseIntegral() != null && orderItem.getUseIntegral().compareTo(BigDecimal.ZERO) > 0) {
                    //记录积分流水
                    IntegralHistory integralHistory = new IntegralHistory();
                    integralHistory.setMemberId(memberId);
                    integralHistory.setAmount(orderItem.getUseIntegral());
                    integralHistory.setOpType(Constants.OptType.AGREE);
                    integralHistory.setSubOpType(25);
                    integralHistory.setOrderAmount(orderItem.getCouponMoney());
                    integralHistory.setOrderId(orderItem.getOrderId());
                    integralHistoryMapper.insert(integralHistory);
                    //修改用户积分
                    Member member = memberMapper.selectById(memberId);
                    if (null == member) {
                        throw new ServiceException("会员信息有误!");
                    }
                    BigDecimal add = member.getIntegral().add(orderItem.getUseIntegral());
                    UpdateWrapper<Member> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("id", memberId);
                    updateWrapper.set("integral", add);
                    memberMapper.update(null, updateWrapper);
                }
            }
        }
        if (orderId != null) {
            //全部退款
            Order order = orderMapper.selectById(orderId);
            if (order == null) {
                throw new ServiceException("订单信息有误!");
            }
            //记录积分流水
            if (order.getTotalIntegral() != null && order.getTotalIntegral().compareTo(BigDecimal.ZERO) > 0) {
                IntegralHistory integralHistory = new IntegralHistory();
                integralHistory.setMemberId(memberId);
                integralHistory.setAmount(order.getTotalIntegral());
                integralHistory.setOpType(Constants.OptType.AGREE);
                integralHistory.setSubOpType(25);
                integral = order.getTotalIntegral();
                integralHistory.setCreateTime(LocalDateTime.now());
                integralHistory.setOrderAmount(order.getPayAmount());
                integralHistory.setOrderId(order.getId());
                integralHistoryMapper.insert(integralHistory);
                //修改用户积分
                Member member = memberMapper.selectById(memberId);
                if (null == member) {
                    throw new ServiceException("会员信息有误!");
                }
                BigDecimal add = member.getIntegral().add(integral);
                UpdateWrapper<Member> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("id", memberId);
                updateWrapper.set("integral", add);
                memberMapper.update(null, updateWrapper);
            }

        }
    }

    /**
     * 订单退款回调MQ
     *
     * @param weChatRefundNotify
     */
    @Transactional
    public void refundOrderExc(RefundNotification weChatRefundNotify) {
        log.info("收到订单回调MQ:" + JSONObject.toJSONString(weChatRefundNotify));
        if ("PROCESSING".equals(weChatRefundNotify.getRefundStatus().name())) {
            return;
        }
    }

    public List<OrderOperateHistoryVO> log(Long orderId) {
        LambdaQueryWrapper<OrderOperateHistory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderOperateHistory::getOrderId, orderId);
        wrapper.in(OrderOperateHistory::getOrderStatus, Arrays.asList(11, 12, 13, 14));
        wrapper.orderByDesc(OrderOperateHistory::getCreateTime);
        List<OrderOperateHistory> historyList = orderOperateHistoryMapper.selectList(wrapper);
        return historyConvert.dos2vos(historyList);
    }

    public Aftersale queryAfterSale(Long orderId) {
        QueryWrapper<Aftersale> itemQw = new QueryWrapper<>();
        itemQw.eq("order_id", orderId);
        itemQw.in("status", Arrays.asList(AftersaleStatus.APPLY.getType(), AftersaleStatus.WAIT.getType()));
        return aftersaleMapper.selectOne(itemQw);
    }
}