package com.hfkj.service.order.impl;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.channel.gas.newlink2.NewLink2RequestService;
import com.hfkj.common.exception.BaseException;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.utils.DateUtil;
import com.hfkj.common.utils.RandomUtils;
import com.hfkj.dao.BsOrderRefundMapper;
import com.hfkj.entity.*;
import com.hfkj.model.order.OrderChildModel;
import com.hfkj.model.order.OrderModel;
import com.hfkj.pay.HuiPayService;
import com.hfkj.service.discount.BsDiscountUserService;
import com.hfkj.service.gas.BsGasOrderService;
import com.hfkj.service.merchant.BsMerchantService;
import com.hfkj.service.order.*;
import com.hfkj.sysenum.gas.GasOrderCreateType;
import com.hfkj.sysenum.gas.OrderOilStatus;
import com.hfkj.sysenum.merchant.MerchantSourceTypeEnum;
import com.hfkj.sysenum.order.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @className: BsOrderRefundServiceImpl
 * @author: HuRui
 * @date: 2024/6/21
 **/
@Service("orderRefundService")
public class BsOrderRefundServiceImpl implements BsOrderRefundService {

    @Resource
    public BsOrderRefundMapper orderRefundMapper;
    @Resource
    private BsOrderService orderService;
    @Resource
    private BsOrderChildService orderChildService;
    @Resource
    private BsMerchantService merchantService;
    @Resource
    private BsOrderSettleService orderSettleService;
    @Resource
    private BsGasOrderService gasOrderService;
    @Resource
    private OrderRefundBusiness orderRefundBusiness;
    @Resource
    private BsDiscountUserService discountUserService;
    @Override
    public void editData(BsOrderRefund data) {
        data.setUpdateTime(new Date());
        if (data.getId() == null) {
            data.setCreateTime(new Date());
            orderRefundMapper.insert(data);
        } else {
            orderRefundMapper.updateByPrimaryKey(data);
        }
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, isolation = Isolation.READ_UNCOMMITTED)
    public Boolean refundMoney(BsOrderRefund orderRefund) {
        try {
            if (OrderPayChannelEnum.type1.getCode() == orderRefund.getRefundPayChannel()) {
                // 交易结算
                BsOrderSettle orderSettle = orderSettleService.getData(orderRefund.getOrderNo());
                if (orderSettle.getLedgerFlag().equals(true) && OrderSettleLedgerStatusEnum.status1.getCode() == orderSettle.getLedgerStatus()) {
                    orderSettleService.revokeLedger(orderSettle);
                    return null;
                }
                // 渠道退款
                JSONObject refund = HuiPayService.refund(orderRefund.getAccountMerchantNo(), orderRefund.getAccountMerchantKey(), orderRefund.getOrderNo(), orderRefund.getRefundOrderNo(), orderRefund.getRefundPrice());
                if (refund.getString("return_code").equals("000000")) {
                    JSONObject data = refund.getJSONObject("return_data");
                    orderRefund.setRefundPayChannelOrderNo(data.getString("refundTradeNo"));
                    orderRefund.setRefundSerialNo(data.getString("accTradeNo"));
                    orderRefund.setRefundStatus(OrderRefundStatusEnum.status2.getCode());
                    orderRefund.setFinishTime(new Date());
                    editData(orderRefund);
                    return true;
                } else {
                    orderRefund.setRefundStatus(OrderRefundStatusEnum.status3.getCode());
                    orderRefund.setRefundFailReason(refund.getString("return_msg"));
                    editData(orderRefund);

                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, orderRefund.getRefundFailReason());
                }

            } else {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！该支付方式暂不支持退款");
            }
        } catch (BaseException e) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.status3.getCode());
            orderRefund.setRefundFailReason(e.getErrorMsg());
            editData(orderRefund);

            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, e.getErrorMsg());

        } catch (Exception e) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.status3.getCode());
            orderRefund.setRefundFailReason("未知问题");
            editData(orderRefund);

            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！");
        }
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW,rollbackFor= {RuntimeException.class})
    public OrderModel tradeOrderRefund(String orderNo, String remark) {
        // 查询交易订单
        OrderModel order = orderService.getDetail(orderNo);
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的订单");
        }
        if (!order.getOrderStatus().equals(OrderStatusEnum.status2.getCode())
            && !order.getOrderStatus().equals(OrderStatusEnum.status3.getCode())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单交易状态错误");
        }

        boolean refundSuccess = true;
        for (OrderChildModel orderChild : order.getOrderChildList()) {
            try {
                BsOrderRefund orderRefund = tradeOrderChildRefund(orderChild.getChildOrderNo(), true, orderChild.getProductCount(), remark);
                if (orderRefund.getRefundStatus().equals(OrderRefundStatusEnum.status3.getCode())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, orderRefund.getRefundFailReason());
                }
            } catch (Exception e) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败");
            }
        }

        order.setOrderStatus(refundSuccess ? OrderStatusEnum.status4.getCode() : order.getOrderStatus());
        order.setRefundTime(refundSuccess ? new Date() : null);
        orderService.editData(order);
        // 删除缓存
        orderService.cacheDelete(order.getOrderNo());

        return order;
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW,rollbackFor= {RuntimeException.class})
    public BsOrderRefund tradeOrderChildRefund(String childOrderNo, Boolean handleBusiness, Integer productCount, String remark) {
        // 查询子订单
        OrderChildModel orderChild = orderChildService.getDetail(childOrderNo);
        if (orderChild == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的子订单");
        }
        if (productCount > orderChild.getSurplusRefundCount()) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！退货数量超过子订单可退数量");
        }
        // 查询交易订单
        OrderModel order = orderService.getDetail(orderChild.getOrderNo());
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的交易订单");
        }
        // 查询交易结算
        BsOrderSettle orderSettle = orderSettleService.getData(order.getOrderNo());
        if (orderSettle  == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的交易结算");
        }
        // 查询商户
        BsMerchant merchant = merchantService.getMerchant(orderChild.getMerNo());
        if (merchant == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的商户");
        }
        if (orderChild.getProductType().equals(OrderChildProductTypeEnum.type1.getCode())) {
            // 加油订单
            BsGasOrder gasOrder = gasOrderService.getDetailByOrderNo(order.getOrderNo());
            if (gasOrder != null) {
                gasOrder.setStatus(OrderOilStatus.STATUS5.getNumber());
                gasOrderService.updateGasOrder(gasOrder);
            }
        }
        // 创建退款订单
        BsOrderRefund orderRefund = new BsOrderRefund();
        orderRefund.setMerId(merchant.getId());
        orderRefund.setMerNo(merchant.getMerNo());
        orderRefund.setOrderNo(orderChild.getOrderNo());
        orderRefund.setOrderChildNo(orderChild.getChildOrderNo());
        orderRefund.setUserId(order.getUserId());
        orderRefund.setUserPhone(order.getUserPhone());
        // 退款订单号 退款标识：R + 时间 + 随机3位数字
        orderRefund.setRefundOrderNo("R"+ DateUtil.date2String(new Date(), "yyMMddHHmmss") + RandomUtils.number(3, false));
        orderRefund.setRefundPayChannel(order.getPayChannel());
        orderRefund.setRefundPayType(order.getPayType());

        if (orderChild.getSurplusRefundCount().equals(productCount)) {
            // 全部退款
            orderRefund.setRefundPrice(orderChild.getSurplusRefundPrice());
            orderRefund.setRefundIntegral(orderChild.getSurplusRefundIntegral());
        } else {
            // 部分退款
            // 计算单价
            BigDecimal unitPrice = orderChild.getSurplusRefundPrice().divide(new BigDecimal(orderChild.getProductCount().toString()), 2, BigDecimal.ROUND_DOWN).setScale(2);
            BigDecimal unitPriceIntegral = new BigDecimal(orderChild.getSurplusRefundIntegral().toString()).divide(new BigDecimal("100"))
                    .divide(new BigDecimal(orderChild.getProductCount().toString()), 2, BigDecimal.ROUND_DOWN).setScale(2);

            orderRefund.setRefundPrice(unitPrice.multiply(new BigDecimal(productCount.toString())));
            orderRefund.setRefundIntegral(unitPriceIntegral.multiply(new BigDecimal("100")).longValue());
        }

    /*    if (orderRefund.getRefundIntegral() > 0L) {
            Map<String,Object> opUser = new HashMap<>();
            opUser.put("opUserType", orderRefund.getOpUserType());
            opUser.put("opUserId", orderRefund.getUserId());
            opUser.put("opUserPhone", orderRefund.getUserPhone());

            Map<String,Object> source = new HashMap<>();
            source.put("sourceType", UserIntegralRecordSourceTypeEnum.type2.getCode());
            source.put("sourceId", orderChild.getId());
            source.put("sourceOrderNo", orderChild.getChildOrderNo());
            source.put("sourceContent", "商品订单退款退回积分");

            // 退款积分
            userIntegralService.entry(orderRefund.getUserId(),orderRefund.getRefundIntegral(), opUser, source);
        }*/
        orderRefund.setRefundRemark(remark);
        orderRefund.setRefundStatus(OrderRefundStatusEnum.status1.getCode());
        orderRefund.setAccountMerchantNo(orderSettle.getSettleMerNo());
        orderRefund.setAccountMerchantKey(orderSettle.getSettleMerKey());
        orderRefund.setCreateType(GasOrderCreateType.TYPE1.getNumber());
        editData(orderRefund);

        // 资金退款
        if (orderChild.getProductType().equals(OrderChildProductTypeEnum.type1.getCode())) {
            // 查询加油订单
            BsGasOrder gasOrder = gasOrderService.getDetailByOrderChildNo(orderChild.getChildOrderNo());
            if (gasOrder == null) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的加油订单");
            }
            if (gasOrder.getAbnormal().equals(true)) {
                // 资金退款
                Boolean refundMoney = refundMoney(orderRefund);
                if (refundMoney != null) {
                    orderRefund.setRefundStatus(refundMoney?OrderRefundStatusEnum.status2.getCode():OrderRefundStatusEnum.status3.getCode());
                    editData(orderRefund);
                }
            } else {
                if (gasOrder.getChannelType().equals(MerchantSourceTypeEnum.type1.getNumber())
                        || gasOrder.getChannelType().equals(MerchantSourceTypeEnum.type3.getNumber())) {
                    // 资金退款
                    Boolean refundMoney = refundMoney(orderRefund);
                    if (refundMoney != null) {
                        orderRefund.setRefundStatus(refundMoney?OrderRefundStatusEnum.status2.getCode():OrderRefundStatusEnum.status3.getCode());
                        editData(orderRefund);
                    }
                } else if (gasOrder.getChannelType().equals(MerchantSourceTypeEnum.type4.getNumber())) {
                    // 申请退款
                    JSONObject refundCallBack = NewLink2RequestService.refundCallBack(gasOrder.getChannelOrderNo(),
                            "其他",
                            orderRefund.getRefundRemark(),
                            orderRefund.getRefundOrderNo());
                    if (!refundCallBack.getString("code").equals("200")) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "申请退款失败:"+refundCallBack.getString("msg"));
                    }
                }
            }
        } else {
            // 资金退款
            Boolean refundMoney = refundMoney(orderRefund);
            if (refundMoney != null) {
                orderRefund.setRefundStatus(refundMoney?OrderRefundStatusEnum.status2.getCode():OrderRefundStatusEnum.status3.getCode());
                editData(orderRefund);
            }
        }

        // 退款成功
        if (orderRefund.getRefundStatus().equals(OrderRefundStatusEnum.status2.getCode())) {
            // 修改子订单可退数量、金额、积分
            orderChild.setSurplusRefundCount(orderChild.getSurplusRefundCount() - productCount);
            orderChild.setSurplusRefundPrice(orderChild.getSurplusRefundPrice().subtract(orderRefund.getRefundPrice()));
            orderChild.setSurplusRefundIntegral(orderChild.getSurplusRefundIntegral() - orderRefund.getRefundIntegral());
            orderChild.setStatus(orderChild.getSurplusRefundCount()==0? OrderChildStatusEnum.status4.getCode():orderChild.getStatus());
            orderChildService.editData(orderChild);

            // 处理退款业务
            if (handleBusiness.equals(true)) {
                if (orderChild.getProductType().equals(OrderChildProductTypeEnum.type1.getCode())) {
                    try {
                        orderRefundBusiness.gasOrder(orderRefund);
                    } catch (BaseException e) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, e.getErrorMsg());
                    } catch (Exception e) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败");
                    }
                }
            }

            // 查询子订单已全部退款
            List<OrderChildModel> orderChildList = orderChildService.getOrderChildListByOrderNo(orderChild.getOrderNo());
            if (orderChildList.size() == orderChildList.stream().filter(o->o.getStatus().equals(OrderChildStatusEnum.status4.getCode())).collect(Collectors.toList()).size()) {
                order.setOrderStatus(OrderStatusEnum.status4.getCode());
                order.setRefundTime(new Date());
                orderService.editData(order);

                if (order.getDeduction().getUserCouponDiscountId() != null) {
                    // 退回优惠券
                    discountUserService.revokeUserDiscount(order.getDeduction().getUserCouponDiscountId());
                }
            }
        }

        // 删除缓存
        orderService.cacheDelete(order.getOrderNo());
        return orderRefund;
    }

    @Override
    public BsOrderRefund getRefund(String refundOrderNo) {
        BsOrderRefundExample example = new BsOrderRefundExample();
        example.createCriteria().andRefundOrderNoEqualTo(refundOrderNo);
        List<BsOrderRefund> list = orderRefundMapper.selectByExample(example);
        if (!list.isEmpty()){
            return list.get(0);
        }
        return null;
    }

    @Override
    public BsOrderRefund getRefundByChildOrderNo(String childOrderNo) {
        BsOrderRefundExample example = new BsOrderRefundExample();
        example.createCriteria().andOrderChildNoEqualTo(childOrderNo).andRefundStatusEqualTo(OrderRefundStatusEnum.status1.getCode());
        example.setOrderByClause("create_time desc");
        List<BsOrderRefund> list = orderRefundMapper.selectByExample(example);
        if (!list.isEmpty()){
            return list.get(0);
        }
        return null;
    }

    @Override
    public BsOrderRefund getRefundByOrderNo(String orderNo) {
        BsOrderRefundExample example = new BsOrderRefundExample();
        example.createCriteria().andOrderNoEqualTo(orderNo).andRefundStatusEqualTo(OrderRefundStatusEnum.status1.getCode());
        example.setOrderByClause("create_time desc");
        List<BsOrderRefund> list = orderRefundMapper.selectByExample(example);
        if (!list.isEmpty()){
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<BsOrderRefund> getRefundList(Map<String, Object> param) {
        BsOrderRefundExample example = new BsOrderRefundExample();
        BsOrderRefundExample.Criteria criteria = example.createCriteria();

        if (StringUtils.isNotBlank(MapUtils.getString(param, "userPhone"))) {
            criteria.andUserPhoneEqualTo(MapUtils.getString(param, "userPhone"));
        }

        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 (MapUtils.getInteger(param, "refundStatus") != null) {
            criteria.andRefundStatusEqualTo(MapUtils.getInteger(param, "refundStatus"));
        }

        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")));
        }

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


}
