package com.gree.mall.manager.logic.order;

import com.aliyuncs.utils.StringUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.gree.mall.manager.bean.ExcelData;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.order.OrderDetailListBean;
import com.gree.mall.manager.bean.order.OrderRefundDetailBean;
import com.gree.mall.manager.commonmapper.OrderRefundInfoMapper;
import com.gree.mall.manager.constant.Constant;
import com.gree.mall.manager.enums.*;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.logic.common.UMSLogic;
import com.gree.mall.manager.logic.common.WechatLogic;
import com.gree.mall.manager.logic.coupon.CouponLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.utils.ArithUtils;
import com.gree.mall.manager.utils.DateUtils;
import com.gree.mall.manager.utils.excel.ExcelUtils;
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.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderRefundLogic {

    @Autowired
    OrderShareLogic orderShareLogic;
    @Autowired
    OrderLogic orderLogic;
    @Autowired
    WechatLogic wechatLogic;
    @Autowired
    CommonLogic commonLogic;
    @Autowired
    CouponLogic couponLogic;
    @Autowired
    OrderInfoService orderInfoService;
    @Autowired
    OrderRefundService orderRefundService;
    @Autowired
    OrderDetailService orderDetailService;
    @Autowired
    ExpressInfoService expressInfoService;
    @Autowired
    OrderRefundInfoMapper orderRefundInfoMapper;
    @Autowired
    OrderRequestService orderRequestService;
    @Autowired
    UMSLogic umsLogic;

    /**
     * 订单列表
     *
     * @return
     */
    public IPage<OrderRefundDetailBean> list(HttpServletRequest request, String orderId, String orderRefundId, String userName, String phone, String orderStatus,
                                             String startCreateTime, String endCreateTime, String startExamineTime, String endExamineTime,
                                             Integer pageNum, Integer pageSize) {
        AdminUserCom adminUser = commonLogic.getAdminUser(request);

        IPage page = orderRefundService.lambdaQuery()
                .like(StringUtils.isNotEmpty(orderId), OrderRefund::getOrderId, orderId)
                .in(CollectionUtils.isNotEmpty(adminUser.getAdminCompanyIds()), OrderRefund::getCompanyId, adminUser.getAdminCompanyIds())
                .in(CollectionUtils.isNotEmpty(adminUser.getAdminWebsitIds()), OrderRefund::getWebsitId, adminUser.getAdminWebsitIds())
                .like(StringUtils.isNotEmpty(orderRefundId), OrderRefund::getOrderRefundId, orderRefundId)
                .like(StringUtils.isNotEmpty(userName), OrderRefund::getUserName, userName)
                .and(StringUtils.isNotEmpty(phone), v -> v.like(OrderRefund::getPhone, phone).or().like(OrderRefund::getRecePhone, phone))
                .eq(StringUtils.isNotEmpty(orderStatus), OrderRefund::getOrderStatus, orderStatus)
                .between(StringUtils.isNotEmpty(startCreateTime) && StringUtils.isNotEmpty(endCreateTime), OrderRefund::getCreateTime, startCreateTime, endCreateTime + " 23:59:59")
                .between(StringUtils.isNotEmpty(startExamineTime) && StringUtils.isNotEmpty(endExamineTime), OrderRefund::getExamineTime, startExamineTime, endExamineTime + " 23:59:59")
                .orderByDesc(OrderRefund::getCreateTime).page(new Page<>(pageNum, pageSize));

        List<OrderRefundDetailBean> list = new ArrayList<>();
        for (Object o : page.getRecords()) {
            OrderRefund orderInfo = (OrderRefund) o;
            OrderRefundDetailBean detailBean = new OrderRefundDetailBean();
            BeanUtils.copyProperties(orderInfo, detailBean);
            //查询订单详情
            List<OrderDetail> orderDetails = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderInfo.getOrderId()).list();
            detailBean.setOrderDetails(orderDetails);

            Integer count = orderRequestService.lambdaQuery().eq(OrderRequest::getOrderId, orderInfo.getOrderId()).count();
            detailBean.setToWorkOrder(count > 0);

            list.add(detailBean);
        }
        page.setRecords(list);
        return page;
    }


    /**
     * 售后订单详情
     *
     * @param orderRefundId
     * @return
     */
    public OrderRefundDetailBean orderRefundDetail(String orderRefundId) {
        OrderRefund orderRefund = orderRefundService.getById(orderRefundId);
        List<OrderDetail> list = orderDetailService.lambdaQuery().eq(OrderDetail::getOrderId, orderRefund.getOrderId()).list();

        OrderRefundDetailBean orderRefundDetailBean = new OrderRefundDetailBean();
        BeanUtils.copyProperties(orderRefund, orderRefundDetailBean);
        orderRefundDetailBean.setOrderDetails(list);
        //售后凭证
        List<CommonFile> commonFiles = commonLogic.queryFileByObjId(orderRefund.getOrderId(), Constant.Img.ORDER_REFUND_WLPZ);
        List<CommonFile> commonFiles2 = commonLogic.queryFileByObjId(orderRefund.getOrderId(), Constant.Img.ORDER_REFUND_TKPZ);
        orderRefundDetailBean.setFiles(commonFiles);
        orderRefundDetailBean.setTkFiles(commonFiles2);
        //工单信息
        List<OrderRequest> orderRequests = orderRequestService.lambdaQuery().eq(OrderRequest::getOrderId, orderRefund.getOrderId()).list();
        orderRefundDetailBean.setOrderRequests(orderRequests);
        return orderRefundDetailBean;
    }

    /**
     * 审核
     */
    @Transactional
    public void examine(String orderRefundId, String examineStatus, String refundMessage, String refundPassword) throws Exception {
        OrderRefund orderRefund = orderRefundService.getById(orderRefundId);
        OrderInfo orderInfo = orderInfoService.getById(orderRefund.getOrderId());
        if (examineStatus.equals(OrderExamineEnum.FAIL.toString())) {
            orderRefundService.lambdaUpdate()
                    .eq(OrderRefund::getOrderRefundId, orderRefundId)
                    .set(OrderRefund::getExamineStatus, examineStatus)
                    .set(OrderRefund::getRefundMessage, refundMessage)
                    .set(OrderRefund::getExamineTime, new Date())
                    .set(OrderRefund::getOrderStatus, OrderStatusEnum.CLOSE.toString())
                    .update();
            orderDetailService.lambdaUpdate()
                    .eq(OrderDetail::getOrderId, orderRefund.getOrderId())
                    .set(OrderDetail::getRefundNum, 0)
                    .set(OrderDetail::getRefundAmount, new BigDecimal("0.00"))
                    .set(OrderDetail::getRefund, false)
                    .update();

            //恢复订单状态
            orderInfo.setOrderStatus(orderInfo.getLastOrderStatus());
            orderInfo.setRefundFlag(RefundFlagEnum.COMMONLY.toString());
            orderInfo.updateById();
            //恢复分佣状态
            orderShareLogic.updateOrderShare(orderInfo.getOrderId(), OrderShareStatusEnum.ING.toString());
            return;
        }
        String orderStatus = OrderStatusEnum.DMJCL.toString();
        if (examineStatus.equals(OrderExamineEnum.OK.toString())) {

            List<OrderShare> orderShareList = orderShareLogic.getOrderShareList(orderInfo.getOrderId());
            if (orderShareList.size() > 0 && orderShareList.get(0).getStatus().equals(OrderShareStatusEnum.OVER.toString())) {
                throw new RemoteServiceException("退款失败,订单已结算");
            }

            if (orderRefund.getRefundType().equals(OrderRefundTypeEnum.REFUND_AMOUNT.toString())) {
                //直接退钱，并直接已完成售后订单
                orderStatus = OrderStatusEnum.OVER.toString();
                //退款
                this.refund(orderRefund);
            }
            orderRefundService.lambdaUpdate()
                    .eq(OrderRefund::getOrderRefundId, orderRefundId)
                    .set(OrderRefund::getExamineStatus, examineStatus)
                    .set(OrderRefund::getRefundMessage, refundMessage)
                    .set(OrderRefund::getExamineTime, new Date())
                    .set(OrderRefund::getOrderStatus, orderStatus)
                    .update();

            String orderId = orderRefund.getOrderId();
            int totalNum = orderInfo.getTotalNum();
            List<OrderDetail> orderDetails = orderDetailService.lambdaQuery()
                    .eq(OrderDetail::getOrderId, orderId)
                    .list();
            int refundNum = orderDetails.stream().filter(OrderDetail::getRefund).collect(Collectors.reducing(0, OrderDetail::getRefundNum, (i, j) -> i + j));
            if (totalNum - refundNum == 0) {
                orderInfoService.lambdaUpdate()
                        .eq(OrderInfo::getOrderId, orderId)
                        .set(OrderInfo::getOrderStatus, OrderStatusEnum.CLOSE.toString())
                        .set(OrderInfo::getRefundFlag, RefundFlagEnum.ALL.toString())
                        .update();
                //退优惠券
                //couponLogic.update(Arrays.asList(orderId));
                couponLogic.refundCoupon(orderInfo.getUserCouponId());
            } else {
                orderInfoService.lambdaUpdate()
                        .eq(OrderInfo::getOrderId, orderId)
                        .set(OrderInfo::getOrderStatus, orderInfo.getLastOrderStatus())
                        .set(OrderInfo::getRefundFlag, RefundFlagEnum.PARTLY.toString())
                        .update();
            }

        }

    }

    /**
     * 商家确认收货
     */
    @Transactional
    public void ack(String orderRefundId) throws Exception {

        OrderRefund orderRefund = orderRefundService.getById(orderRefundId);

        orderRefundService.lambdaUpdate()
                .set(OrderRefund::getOverTime, new Date())
                .set(OrderRefund::getOrderStatus, OrderStatusEnum.OVER.toString())
                .eq(OrderRefund::getOrderRefundId, orderRefundId).update();
        //退款
        this.refund(orderRefund);
    }

    /**
     * 查看物流
     */
    public List<ExpressInfo> queryExpressInfo(String logisticsNo) {
        List<ExpressInfo> list = expressInfoService.lambdaQuery()
                .eq(ExpressInfo::getLogisticsNo, logisticsNo).list();
        if (CollectionUtils.isNotEmpty(list)) {
            return list;
        }
        return null;
    }


    /**
     * 备注
     */
    public void remark(String orderRefundId, String remark) {
        orderRefundService.lambdaUpdate().set(OrderRefund::getRemark, remark).eq(OrderRefund::getOrderRefundId, orderRefundId).update();
    }


    /**
     * 退款
     *
     * @param orderRefund
     * @throws RemoteServiceException
     * @throws WxPayException
     */
    public void refund(OrderRefund orderRefund) throws Exception {
        String orderId = orderRefund.getOrderId();
        List<OrderDetail> list = orderDetailService.lambdaQuery()
                .eq(OrderDetail::getOrderId, orderId)
                .eq(OrderDetail::getRefund, true).list();

        for (OrderDetail orderDetail : list) {
            double div = ArithUtils.div(orderDetail.getRefundNum(), orderDetail.getNum(), 4);
            double mul = ArithUtils.mul(orderDetail.getShareAmount().doubleValue(), div, 2);
            BigDecimal totalShareAmount = BigDecimal.valueOf(mul);

            //1=非团购商品 2=团购商品
            int flag = StringUtils.isNotEmpty(orderDetail.getPromotionGroupId()) ? 2 : 1;
            log.info("【退款开始：】重置结算flag={}金额，需要减掉的金额{}", flag, totalShareAmount.doubleValue());
            orderShareLogic.reloadAmount(orderId, totalShareAmount, flag);
        }

        log.info("【退款开始：】退款金额{}", orderRefund.getRefundAmount().doubleValue());
        if (orderRefund.getPayAmount().doubleValue() == 0) {
            return;
        }
        if (!orderRefund.getPayType().equals("云闪付")) {
            wechatLogic.refund(orderRefund.getOrderId(), orderRefund.getOrderRefundId(), orderRefund.getPayAmount().doubleValue()
                    , orderRefund.getRefundAmount().doubleValue(), orderRefund.getPayWorkerCodeId());
        } else {
            umsLogic.refund(orderRefund.getOrderId(), orderRefund.getPayAmount().doubleValue()
                    , orderRefund.getRefundAmount().doubleValue(), orderRefund.getWebsitId());
        }
    }


    /**
     * 导出报表
     */
    public void downLoadOrderRefundExcel(HttpServletRequest request, HttpServletResponse response,
                                         String orderId, String orderRefundId, String userName, String phone, String orderStatus,
                                         String startCreateTime, String endCreateTime, String startExamineTime, String endExamineTime
    ) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser(request);

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        List<List<Object>> rowList = new ArrayList<>();

        String[] titles = {"订单号", "商品名称", "规格型号", "数量", "单位", "销售单价", "优惠后单价", "实际收款", "收货人姓名",
                "手机号", "收货地址", "订单状态", "售后状态", "退款金额(小项)", "退款数量(小项)", "备注", "下单时间", "买家昵称", "购买渠道",
                "买家备注", "卖家备注", "网点", "业务员/网点", "分佣金额", "团长名称", "团长手机号", "团购活动id", "退货说明"};
        ExcelData excelData = new ExcelData();
        excelData.setTitles(Arrays.asList(titles));
        excelData.setName("维权订单");
        excelData.setRows(rowList);

        List<OrderDetailListBean> orderRefundDetailList = orderRefundInfoMapper.getOrderRefundDetailList(
                orderId, orderRefundId, userName, phone, orderStatus, startCreateTime, endCreateTime, startExamineTime, endExamineTime, adminUser.getAdminCompanyIds(), adminUser.getAdminWebsitIds());

        for (OrderDetailListBean orderDetailListBean : orderRefundDetailList) {
            List<Object> row = new ArrayList<>();
            rowList.add(row);

            row.add(orderDetailListBean.getOrderId());
            row.add(orderDetailListBean.getGoodsName());
            row.add(orderDetailListBean.getGoodsSpecValue());
            row.add(orderDetailListBean.getNum());
            row.add("台");
            row.add(orderDetailListBean.getPrice());
            row.add(orderDetailListBean.getPayAmount().divide(new BigDecimal(orderDetailListBean.getNum()), 2, BigDecimal.ROUND_HALF_UP));
            row.add(orderDetailListBean.getPayAmount());
            row.add(orderDetailListBean.getReceUserName());
            row.add(orderDetailListBean.getRecePhone());
            row.add(orderDetailListBean.getAddress());
            if (StringUtils.isNotEmpty(orderDetailListBean.getOrderStatus())) {
                row.add(Enum.valueOf(OrderStatusEnum.class, orderDetailListBean.getOrderStatus()).getName());
            } else {
                row.add("");
            }
            if (StringUtils.isNotEmpty(orderDetailListBean.getRefundFlag())) {
                row.add(RefundFlagEnum.valueOf(orderDetailListBean.getRefundFlag()).getName());
            } else {
                row.add("");
            }
            row.add(orderDetailListBean.getRefundAmount());
            row.add(orderDetailListBean.getRefundNum());
            row.add(orderDetailListBean.getRemark());
            row.add(DateUtils.formatDate(orderDetailListBean.getCreateTime()));
            row.add(orderDetailListBean.getUserName());
            row.add(orderDetailListBean.getWorkerName());
            row.add(orderDetailListBean.getBuyerMsg());
            row.add(orderDetailListBean.getRefundMessage());
            row.add(orderDetailListBean.getWebsitName());
            row.add(orderDetailListBean.getWorkerNameWithWebsitName());
            row.add(orderDetailListBean.getShareAmount());
            row.add(orderDetailListBean.getNickName());
            row.add(orderDetailListBean.getMobile());
            row.add(orderDetailListBean.getPromotionGroupId());
            row.add(orderDetailListBean.getRefundExplain());

        }


        ExcelUtils.exportExcel(request, response, String.format("维权订单导出%s.xlsx", simpleDateFormat.format(new Date())), excelData);

    }

}
