package com.hai.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.utils.DateUtil;
import com.hai.config.HuiLianTongUnionCardConfig;
import com.hai.config.UnionPayConfig;
import com.hai.config.WxOrderConfig;
import com.hai.dao.HighOrderRefundMapper;
import com.hai.entity.HighChildOrder;
import com.hai.entity.HighOrder;
import com.hai.entity.HighOrderRefund;
import com.hai.entity.HighOrderRefundExample;
import com.hai.model.OrderRefundModel;
import com.hai.openApi.service.ApiOrderService;
import com.hai.order.model.RefundPriceModel;
import com.hai.order.service.OrderRefundService;
import com.hai.order.service.OrderService;
import com.hai.order.type.*;
import com.hai.order.utils.OrderUtil;
import com.hai.service.HighFleetOilCardService;
import com.hai.service.HighOilCardService;
import com.hai.service.HighUserService;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @className: OrderRefundServiceImpl
 * @author: HuRui
 * @date: 2022/9/1
 **/
@Service("orderRefundService")
public class OrderRefundServiceImpl implements OrderRefundService {

    @Resource
    private HighOrderRefundMapper orderRefundMapper;

    @Resource
    private HighUserService userService;

    @Resource
    private OrderService orderService;

    @Resource
    private HighUserService highUserService;

    @Resource
    private HighOilCardService oilCardService;

    @Resource
    private HighFleetOilCardService fleetOilCardService;

    @Resource
    private ApiOrderService apiOrderService;

    @Override
    public void update(HighOrderRefund orderRefund) {
        orderRefundMapper.updateByPrimaryKey(orderRefund);
    }

    @Override
    public HighOrder createOrderRefund(String refundOrderNo, HighOrder order, String remarks, OrderRefundOpUserType opUserType, Long opUserId, String opUserName) throws Exception {
        for (HighChildOrder orderChild : order.getHighChildOrderList()) {
            // 创建退款记录
            HighOrderRefund orderRefund = createOrderChildRefund(orderChild, refundOrderNo, orderChild.getSaleCount(), remarks, opUserType,opUserId,opUserName);
            orderChild.setSurplusRefundNum(orderChild.getSurplusRefundNum() - orderRefund.getRefundGoodsNum());
            orderChild.setSurplusRefundPrice(orderChild.getSurplusRefundPrice().subtract(orderRefund.getRefundPrice()));
            orderChild.setSurplusRefundIntegral(orderChild.getSurplusRefundIntegral() - orderRefund.getRefundIntegral());
            if (orderChild.getSurplusRefundNum() == 0) {
                orderChild.setChildOrderStatus(OrderChildStatus.STATUS6.getNumber());
            }
        }
        return order;
    }

    @Override
    public HighOrderRefund createOrderChildRefund(HighChildOrder orderChild, String refundOrderNo, Integer refundGoodsCount, String remarks, OrderRefundOpUserType opUserType, Long opUserId, String opUserName) throws Exception {
        if (!orderChild.getChildOrderStatus().equals(OrderChildStatus.STATUS2.getNumber())
            && !orderChild.getChildOrderStatus().equals(OrderChildStatus.STATUS3.getNumber())){
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "子订单状态错误");
        }
        if (orderChild.getSurplusRefundIntegral() <= 0
                && orderChild.getSurplusRefundPrice().compareTo(new BigDecimal("0")) <= 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "子订单余额不足");
        }
        // 判断剩余可退商品数量
        if (orderChild.getSurplusRefundNum() < refundGoodsCount) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款商品数量超过剩余退款数量");
        }
        // 交易订单
        HighOrder order = orderService.getOrderDetailByNo(orderChild.getOrderNo());
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "交易订单不存在");
        }
        // 退款金额   剩余退款金额 / 退款数量
        BigDecimal refundPrice = orderChild.getSurplusRefundPrice().divide(new BigDecimal(refundGoodsCount.toString())).setScale(2, BigDecimal.ROUND_DOWN);
        // 退款积分   剩余退款积分 / 退款数量
        Integer refundIntegral = new BigDecimal(orderChild.getSurplusRefundIntegral().toString()).divide(new BigDecimal(refundGoodsCount.toString()), 0, BigDecimal.ROUND_DOWN).intValue();

        HighOrderRefund orderRefund = new HighOrderRefund();
        orderRefund.setOrderId(orderChild.getOrderId());
        orderRefund.setOrderNo(orderChild.getOrderNo());
        orderRefund.setPayType(order.getPayType());
        orderRefund.setOrderChildId(orderChild.getId());
        orderRefund.setOrderChildNo(orderChild.getChildOrderNo());
        orderRefund.setMemId(orderChild.getMemId());
        orderRefund.setMemName(orderChild.getMemName());
        orderRefund.setMemPhone(orderChild.getMemPhone());
        orderRefund.setGoodsType(orderChild.getGoodsType());
        orderRefund.setGoodsId(orderChild.getGoodsId());
        orderRefund.setGoodsName(orderChild.getGoodsName());
        orderRefund.setGoodsDesc(orderChild.getGoodsDesc());
        orderRefund.setGoodsImg(orderChild.getGoodsImg());
        orderRefund.setGoodsSpecName(orderChild.getGoodsSpecName());
        orderRefund.setGoodsCount(orderChild.getSaleCount());
        orderRefund.setRefundOrderNo(refundOrderNo==null?OrderUtil.generateRefundOrderNo():refundOrderNo);
        orderRefund.setRefundGoodsNum(refundGoodsCount);
        orderRefund.setReturnTotalPrice(refundPrice.add(new BigDecimal(refundIntegral).divide(new BigDecimal("100"))));
        orderRefund.setRefundPrice(refundPrice);
        orderRefund.setRefundIntegral(refundIntegral);
        orderRefund.setRefundRemark(remarks);
        orderRefund.setRefundStatus(OrderRefundStatus.STATUS1.getNumber());
        orderRefund.setCreateTime(new Date());
        orderRefund.setUpdateTime(new Date());
        orderRefund.setOpUserType(opUserType.getNumber());
        orderRefund.setOpUserId(opUserId);
        orderRefund.setOpUserName(opUserName);

        if (order.getPayType().equals(OrderPayType.PAY_TYPE4.getNumber())
                || order.getPayType().equals(OrderPayType.PAY_TYPE7.getNumber())
                || order.getPayType().equals(OrderPayType.PAY_TYPE8.getNumber())) {
            orderRefund.setAccountMerchantNum(order.getMemCardNo());
        } else {
            orderRefund.setAccountMerchantNum(order.getAccountMerchantNum());
        }

        orderRefundMapper.insert(orderRefund);
        return orderRefund;
    }

    @Override
    public RefundPriceModel refundPrice(String refundOrderNo, HighOrder order, OrderPayType orderPayType, BigDecimal refundPrice, Integer refundIntegral) {
        RefundPriceModel refundPriceModel = new RefundPriceModel();
        refundPriceModel.setRefundSuccess(false);
        refundPriceModel.setRefundOrderNo(refundOrderNo);
        try {
            // 积分退款
            if (refundIntegral != null && refundIntegral > 0) {
                String remark = "订单" + order.getOrderNo() + "退款，退还积分：" +  refundIntegral;
                // 积分退款
                highUserService.goldHandle(order.getMemId(), order.getPayGold(),1, 3, order.getId() , remark , order.getOrderNo());
            }

            // 第三方退款
            if (orderPayType.getNumber().equals(OrderPayType.PAY_TYPE2.getNumber())) {
                // 微信退款
                OrderRefundModel orderRefundModel = WxOrderConfig.orderToRefund(order.getPaySerialNo(),order.getPayRealPrice(), order.getAccountMerchantNum(), refundPrice);
                if(orderRefundModel.getResult_code().equals("SUCCESS")) {
                    refundPriceModel.setRefundSuccess(true);
                    refundPriceModel.setThirdPartyRefundOrderNo(orderRefundModel.getRefund_id());
                }

            } else if (orderPayType.getNumber().equals(OrderPayType.PAY_TYPE3.getNumber())) {
                refundPriceModel.setRefundSuccess(true);

            } else if (orderPayType.getNumber().equals(OrderPayType.PAY_TYPE4.getNumber())) {

                JSONObject refund = HuiLianTongUnionCardConfig.refund(refundOrderNo, order.getOrderNo());
                if (!refund.getString("respCode").equals("0000")) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR,refund.getString("respMessage"));
                }
                JSONObject consumptionResult = HuiLianTongUnionCardConfig.resolveResponse(refund.getString("data"));
                if (!(consumptionResult.getBoolean("success") || Objects.equals(consumptionResult.getString("message"), "原交易已撤销,不可再次操作"))) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "交易失败!"+consumptionResult.getString("message"));
                }
                refundPriceModel.setRefundSuccess(true);
                refundPriceModel.setThirdPartyRefundOrderNo(consumptionResult.getString("orderId"));

            } else if (orderPayType.getNumber().equals(OrderPayType.PAY_TYPE5.getNumber())) {
                Calendar startTime = Calendar.getInstance();
                startTime.set(Calendar.HOUR_OF_DAY, 00);
                startTime.set(Calendar.MINUTE, 00);
                startTime.set(Calendar.SECOND, 00);

                Calendar endTime = Calendar.getInstance();
                startTime.set(Calendar.HOUR_OF_DAY, 23);
                startTime.set(Calendar.MINUTE, 59);
                startTime.set(Calendar.SECOND, 59);

                // 订单是否处于当日的订单
                if (DateUtil.format(order.getPayTime(), "yyyy-MM-dd").equals(DateUtil.format(new Date(), "yyyy-MM-dd"))) {
                    // 订单撤销
                    JSONObject refund = UnionPayConfig.cancel(UnionPayConfig.MER_ID2, UnionPayConfig.TERM_ID2, order.getOrderNo(), order.getPaySerialNo());
                    System.out.println(refund.toJSONString());
                    if (refund.getString("resultcode").equals("00") || refund.getString("resultcode").equals("W6")) {
                        refundPriceModel.setRefundSuccess(true);
                    } else {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, refund.getString("returnmsg"));
                    }

                } else {
                    // 订单退款
                    JSONObject refund = UnionPayConfig.zwrefund(UnionPayConfig.MER_ID2, UnionPayConfig.TERM_ID2, order.getOrderNo(), order.getPaySerialNo(), order.getPayRealPrice().multiply(new BigDecimal("100")).longValue());
                    System.out.println(refund.toJSONString());
                    if (refund.getString("resultcode").equals("00") || refund.getString("resultcode").equals("W6")) {
                        refundPriceModel.setRefundSuccess(true);
                    } else {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, refund.getString("returnmsg"));
                    }
                }
            } else if (orderPayType.getNumber().equals(OrderPayType.PAY_TYPE7.getNumber())) {
                // 油卡退款
                oilCardService.refund(order.getOrderNo());
                refundPriceModel.setRefundSuccess(true);

            } else if (orderPayType.getNumber().equals(OrderPayType.PAY_TYPE8.getNumber())) {
                // 油卡退款
                fleetOilCardService.refund(order.getOrderNo());
                refundPriceModel.setRefundSuccess(true);
            } else if (orderPayType.getNumber().equals(OrderPayType.PAY_TYPE9.getNumber())) {
                // 商户退款
                apiOrderService.refund(order.getOrderNo());
                refundPriceModel.setRefundSuccess(true);
            }

        } catch (Exception e) {
            refundPriceModel.setRefundSuccess(false);
        }
        return refundPriceModel;
    }

    @Override
    public List<HighOrderRefund> getRefundOrderList(Map<String, Object> param) {
        HighOrderRefundExample example = new HighOrderRefundExample();
        HighOrderRefundExample.Criteria criteria = example.createCriteria();

        if (StringUtils.isNotBlank(MapUtils.getString(param, "orderNo"))) {
            criteria.andOrderNoLike("%"+MapUtils.getString(param, "orderNo")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "orderChildNo"))) {
            criteria.andOrderChildNoLike("%"+MapUtils.getString(param, "orderChildNo")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "refundOrderNo"))) {
            criteria.andRefundOrderNoLike("%"+MapUtils.getString(param, "refundOrderNo")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "memPhone"))) {
            criteria.andMemPhoneEqualTo(MapUtils.getString(param, "memPhone"));
        }

        if (MapUtils.getInteger(param, "payType") != null) {
            criteria.andPayTypeEqualTo(MapUtils.getInteger(param, "payType"));
        }

        if (MapUtils.getLong(param, "memId") != null) {
            criteria.andMemIdEqualTo(MapUtils.getLong(param, "memId"));
        }

        if (MapUtils.getInteger(param, "goodsType") != null) {
            criteria.andGoodsTypeEqualTo(MapUtils.getInteger(param, "goodsType"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "goodsName"))) {
            criteria.andGoodsNameLike("%"+MapUtils.getString(param, "goodsName")+"%");
        }

        if (MapUtils.getInteger(param, "status") != null) {
            criteria.andRefundStatusEqualTo(MapUtils.getInteger(param, "status"));
        }

        if (MapUtils.getLong(param, "createTimeS") != null) {
            criteria.andCreateTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "createTimeS")));
        }

        if (MapUtils.getLong(param, "createTimeE") != null) {
            criteria.andCreateTimeLessThanOrEqualTo(new Date(MapUtils.getLong(param, "createTimeE")));
        }

        if (MapUtils.getLong(param, "refundTimeS") != null) {
            criteria.andRefundTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "refundTimeS")));
        }
        if (MapUtils.getLong(param, "refundTimeE") != null) {
            criteria.andRefundTimeLessThanOrEqualTo(new Date(MapUtils.getLong(param, "refundTimeE")));
        }

        example.setOrderByClause("create_time desc");
        return orderRefundMapper.selectByExample(example);
    }

    @Override
    public  List<HighOrderRefund> getRefundByRefundNo(String refundOrderNo) {
        HighOrderRefundExample example = new HighOrderRefundExample();
        example.createCriteria().andRefundOrderNoEqualTo(refundOrderNo);
        example.setOrderByClause("create_time desc");
        return orderRefundMapper.selectByExample(example);
    }

}
