package com.hfkj.service.order.impl;

import com.alibaba.fastjson.JSONObject;
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.BsMerPayConfig;
import com.hfkj.entity.BsOrder;
import com.hfkj.entity.BsOrderRefund;
import com.hfkj.entity.BsOrderRefundExample;
import com.hfkj.mer.BsMerPayConfigService;
import com.hfkj.model.order.OrderChildModel;
import com.hfkj.model.order.OrderModel;
import com.hfkj.service.hlt.HltCardRefundService;
import com.hfkj.service.hlt.HuiLianTongUnionCardService;
import com.hfkj.service.order.BsOrderChildService;
import com.hfkj.service.order.BsOrderRefundService;
import com.hfkj.service.order.BsOrderService;
import com.hfkj.service.order.OrderRefundSuccessService;
import com.hfkj.service.pay.HuiPayService;
import com.hfkj.service.pay.huift.TradeService;
import com.hfkj.service.user.UserIntegralService;
import com.hfkj.sysenum.UserIntegralRecordOpUserTypeEnum;
import com.hfkj.sysenum.UserIntegralRecordSourceTypeEnum;
import com.hfkj.sysenum.mer.PayPlatformEnum;
import com.hfkj.sysenum.order.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
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.*;

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

    @Resource
    public BsOrderRefundMapper orderRefundMapper;
    @Resource
    private BsOrderService orderService;
    @Resource
    private BsOrderChildService orderChildService;
    @Resource
    private UserIntegralService userIntegralService;
    @Resource
    private TradeService huiftTradeService;
    @Resource
    private HltCardRefundService hltCardRefundService;
    @Resource
    private OrderRefundSuccessService orderRefundSuccessService;
    @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()) {
                // 渠道退款
                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);
                }

            } else if (OrderPayChannelEnum.type3.getCode() == orderRefund.getRefundPayChannel()) {
                // 商户退款
                JSONObject refundObj = huiftTradeService.thirdPayRefund(orderRefund.getRefundOrderNo(), orderRefund.getRefundPrice(), orderRefund.getOrderNo());
                orderRefund.setRefundSerialNo(refundObj.getString("refundTraceNo"));
                orderRefund.setRefundPayChannelOrderNo(refundObj.getString("refundOrderNo"));
                return true;

            } else if (OrderPayChannelEnum.type4.getCode() == orderRefund.getRefundPayChannel()) {
                // 商户退款
                return hltCardRefundService.refund(orderRefund);
            } else {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！该支付方式暂不支持退款");
            }
        } catch (BaseException e) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.status3.getCode());
            orderRefund.setRefundFailReason(e.getErrorMsg());
            editData(orderRefund);

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

    @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())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "该账户已被禁用，无法进行交易");
        }

        boolean refundSuccess = true;
        for (OrderChildModel orderChild : order.getOrderChildList()) {
            try {
                tradeOrderChildRefund(orderChild.getChildOrderNo(), orderChild.getProductCount(), remark);
            } catch (Exception e) {
                refundSuccess = false;
            }
        }
        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, 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, "退款失败！退货数量超过子订单可退数量");
        }
        // 查询交易订单
        BsOrder order = orderService.getOrder(orderChild.getOrderNo());
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的交易订单");
        }

        // 创建退款订单
        BsOrderRefund orderRefund = new BsOrderRefund();
        orderRefund.setMerId(orderChild.getMerId());
        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.setReufndPayType(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(orderChild.getSettleAccount());
        orderRefund.setAccountMerchantKey(orderChild.getSettleAccountKey());
        editData(orderRefund);

        // 资金退款
        orderRefund.setRefundStatus(refundMoney(orderRefund)?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());

            // 退款业务处理
            orderRefundSuccessService.orderRefundHandle(orderChild);

            orderChildService.editData(orderChild);
        }

        // 删除缓存
        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 List<BsOrderRefund> getRefundList(Map<String, Object> param) {
        BsOrderRefundExample example = new BsOrderRefundExample();
        BsOrderRefundExample.Criteria criteria = example.createCriteria();

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

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

}
